AMBARI-23456. Generate markdown docs from internal annotations. (#53)

* AMBARI-23456. Generate markdown docs from internal annotations.

* fix typo

* fix another typo

* Fix typos that depend on last changes

* prop-doc: depends on install, also without install

* Review changes

* fix typo

* add missing list item tag

* fix another typo
diff --git a/Makefile b/Makefile
index 5f9c8b0..cfeaada 100644
--- a/Makefile
+++ b/Makefile
@@ -46,6 +46,12 @@
 deb:
 	$(MAVEN_BINARY) clean package -Dbuild-deb -DskipTests -Djdk.version=$(LOGSEARCH_JAVA_VERSION)
 
+prop-docs: install
+	$(MAVEN_BINARY) -pl ambari-logsearch-docs exec:java -DskipTests -Djdk.version=$(LOGSEARCH_JAVA_VERSION)
+
+prop-docs-only:
+	$(MAVEN_BINARY) -pl ambari-logsearch-docs clean package exec:java -DskipTests -Djdk.version=$(LOGSEARCH_JAVA_VERSION)
+
 update-version:
 	$(MAVEN_BINARY) versions:set-property -Dproperty=revision -DnewVersion=$(new-version) -DgenerateBackupPoms=false
 
diff --git a/ambari-logsearch-docs/pom.xml b/ambari-logsearch-docs/pom.xml
new file mode 100644
index 0000000..f43117c
--- /dev/null
+++ b/ambari-logsearch-docs/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>ambari-logsearch</artifactId>
+    <groupId>org.apache.ambari</groupId>
+    <version>${revision}</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>jar</packaging>
+  <url>http://maven.apache.org</url>
+  <name>Ambari Logsearch Docs</name>
+  <artifactId>ambari-logsearch-docs</artifactId>
+  <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>${jdk.version}</source>
+          <target>${jdk.version}</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <version>1.2.1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>java</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <mainClass>org.apache.ambari.logsearch.doc.LogSearchMarkdownGenerator</mainClass>
+          <arguments>
+            <argument>--output-dir</argument>
+            <argument>${project.basedir}/../docs</argument>
+          </arguments>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-logsearch-logfeeder</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-logsearch-server</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+
+</project>
\ No newline at end of file
diff --git a/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/AbstractDescriptionData.java b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/AbstractDescriptionData.java
new file mode 100644
index 0000000..e95d2ea
--- /dev/null
+++ b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/AbstractDescriptionData.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ambari.logsearch.doc;
+
+public abstract class AbstractDescriptionData {
+
+  private final String description;
+  private final String defaultValue;
+  private final String examples;
+
+  public AbstractDescriptionData(String description, String defaultStr, String[] examplesArr) {
+    this.description = description;
+    examples = generateExamplesString(examplesArr);
+    defaultValue = generateDefaultValue(defaultStr);
+  }
+
+  protected String generateDefaultValue(String defaultValue) {
+    if (defaultValue == null || defaultValue.length() == 0) {
+      return "`EMPTY`";
+    } else {
+      return defaultValue;
+    }
+  }
+
+  protected String generateExamplesString(String[] examples) {
+    if (examples == null) {
+      return "";
+    } else {
+      final StringBuilder stringBuilder = new StringBuilder();
+      if(examples.length > 0){
+        stringBuilder.append("<ul>");
+        for( String example : examples){
+          stringBuilder.append("<li>").append("`").append(example).append("`").append("</li>");
+        }
+        stringBuilder.append("</ul>");
+      }
+      return stringBuilder.toString();
+    }
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public String getDefaultValue() {
+    return defaultValue;
+  }
+
+  public String getExamples() {
+    return examples;
+  }
+}
diff --git a/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/LogSearchMarkdownGenerator.java b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/LogSearchMarkdownGenerator.java
new file mode 100644
index 0000000..c75131f
--- /dev/null
+++ b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/LogSearchMarkdownGenerator.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ambari.logsearch.doc;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import org.apache.ambari.logsearch.config.api.LogSearchPropertyDescription;
+import org.apache.ambari.logsearch.config.api.ShipperConfigElementDescription;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.io.FileUtils;
+import org.reflections.Reflections;
+import org.reflections.scanners.FieldAnnotationsScanner;
+import org.reflections.scanners.MethodAnnotationsScanner;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+public class LogSearchMarkdownGenerator {
+
+  private static final String SHIPPER_CONFIG_TEMPLATE_KEY = "shipperConfigs";
+  private static final String LOGSEARCH_PROPERTIES_TEMPLATE_KEY = "logsearchProperties";
+  private static final String LOGFEEDER_PROPERTIES_TEMPLATE_KEY = "logfeederProperties";
+
+  private static final String OUTPUT_DIR_OPTION = "output-dir";
+
+  private static final String LOGSEARCH_PACKAGE = "org.apache.ambari.logsearch";
+  private static final String LOGFEEDER_PACKAGE = "org.apache.ambari.logfeeder";
+  private static final String CONFIG_API_PACKAGE = "org.apache.ambari.logsearch.config.json.model.inputconfig.impl";
+
+  private static final String TEMPLATES_FOLDER = "templates";
+
+  private static final String LOGSEARCH_PROPERTIES = "logsearch.properties";
+  private static final String LOGSEARCH_PROPERTIES_MARKDOWN_TEMPLATE_FILE = "logsearch_properties.md.ftl";
+  private static final String LOGSEARCH_PROPERTIES_MARKDOWN_OUTPUT = "logsearch_properties.md";
+
+  private static final String LOGFEEDER_PROPERTIES = "logfeeder.properties";
+  private static final String LOGFEEDER_PROPERTIES_MARKDOWN_TEMPLATE_FILE = "logfeeder_properties.md.ftl";
+  private static final String LOGFEEDER_PROPERTIES_MARKDOWN_OUTPUT = "logfeeder_properties.md";
+
+  private static final String SHIPPER_CONFIGURATIONS_MARKDOWN_TEMPLATE_FILE = "shipper_configurations.md.ftl";
+  private static final String SHIPPER_CONFIGURATIONS_MARKDOWN_OUTPUT = "shipper_configurations.md";
+
+
+  public static void main(String[] args) {
+    try {
+      Options options = new Options();
+      options.addOption(Option.builder()
+        .desc("Output folder of the markdowns")
+        .longOpt(OUTPUT_DIR_OPTION)
+        .hasArg()
+        .required()
+        .type(String.class)
+        .build());
+      CommandLineParser parser = new DefaultParser();
+      CommandLine cmdLine = parser.parse(options, args);
+
+      String outputDir = cmdLine.getOptionValue(OUTPUT_DIR_OPTION);
+      File outputFileDir = new File(outputDir);
+      if (!outputFileDir.exists() || !outputFileDir.isDirectory()) {
+        throw new FileNotFoundException(String.format("Directory '%s' does not exist", outputDir));
+      }
+
+      final Map<String, List<PropertyDescriptionData>> propertyDescriptions = new ConcurrentHashMap<>();
+      final List<String> configPackagesToScan = Arrays.asList(LOGSEARCH_PACKAGE, LOGFEEDER_PACKAGE);
+      fillPropertyDescriptions(propertyDescriptions, configPackagesToScan);
+      System.out.println(String.format("Number of logsearch.properties configuration descriptors found: %d", propertyDescriptions.get(LOGSEARCH_PROPERTIES).size()));
+      System.out.println(String.format("Number of logfeeder.properties configuration descriptors found: %d", propertyDescriptions.get(LOGFEEDER_PROPERTIES).size()));
+
+      final List<String> shipperConfigPackagesToScan = Collections.singletonList(CONFIG_API_PACKAGE);
+      ShipperConfigDescriptionDataHolder shipperConfigDescriptionDataHolder = createShipperConfigDescriptions(shipperConfigPackagesToScan);
+
+      System.out.println(String.format("Number of top level section shipper descriptors found: %d", shipperConfigDescriptionDataHolder.getTopLevelConfigSections().size()));
+      System.out.println(String.format("Number of input config section shipper descriptors found: %d", shipperConfigDescriptionDataHolder.getInputConfigSections().size()));
+      System.out.println(String.format("Number of filter config section shipper descriptors found: %d", shipperConfigDescriptionDataHolder.getFilterConfigSections().size()));
+      System.out.println(String.format("Number of mapper section shipper descriptors found: %d", shipperConfigDescriptionDataHolder.getPostMapValuesConfigSections().size()));
+
+      final Configuration freemarkerConfiguration = new Configuration();
+      final ClassPathResource cpr = new ClassPathResource(TEMPLATES_FOLDER);
+      freemarkerConfiguration.setDirectoryForTemplateLoading(cpr.getFile());
+
+      final Map<String, Object> logsearchModels = new HashMap<>();
+      logsearchModels.put(LOGSEARCH_PROPERTIES_TEMPLATE_KEY, propertyDescriptions.get(LOGSEARCH_PROPERTIES));
+      File logsearchPropertiesOutputFile = Paths.get(outputDir,LOGSEARCH_PROPERTIES_MARKDOWN_OUTPUT).toFile();
+      writeMarkdown(freemarkerConfiguration, LOGSEARCH_PROPERTIES_MARKDOWN_TEMPLATE_FILE, logsearchModels, logsearchPropertiesOutputFile);
+
+      final Map<String, Object> logfeederModels = new HashMap<>();
+      logfeederModels.put(LOGFEEDER_PROPERTIES_TEMPLATE_KEY, propertyDescriptions.get(LOGFEEDER_PROPERTIES));
+      File logfeederPropertiesOutputFile = Paths.get(outputDir, LOGFEEDER_PROPERTIES_MARKDOWN_OUTPUT).toFile();
+      writeMarkdown(freemarkerConfiguration, LOGFEEDER_PROPERTIES_MARKDOWN_TEMPLATE_FILE, logfeederModels, logfeederPropertiesOutputFile);
+
+      final Map<String, Object> shipperConfigModels = new HashMap<>();
+      shipperConfigModels.put(SHIPPER_CONFIG_TEMPLATE_KEY, shipperConfigDescriptionDataHolder);
+
+      File shipperConfigsOutputFile = Paths.get(outputDir, SHIPPER_CONFIGURATIONS_MARKDOWN_OUTPUT).toFile();
+      writeMarkdown(freemarkerConfiguration, SHIPPER_CONFIGURATIONS_MARKDOWN_TEMPLATE_FILE, shipperConfigModels, shipperConfigsOutputFile);
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      System.exit(1);
+    }
+  }
+
+  private static void writeMarkdown(Configuration freemarkerConfiguration, String templateName,
+                                    Map<String, Object> models, File outputFile) throws Exception {
+    final StringWriter stringWriter = new StringWriter();
+    final Template template = freemarkerConfiguration.getTemplate(templateName);
+    template.process(models, stringWriter);
+    FileUtils.writeStringToFile(outputFile, stringWriter.toString(), Charset.defaultCharset(), false);
+  }
+
+  private static void fillPropertyDescriptions(Map<String, List<PropertyDescriptionData>> propertyDescriptions, List<String> packagesToScan) {
+    List<PropertyDescriptionData> propertyDescriptionsList = getPropertyDescriptions(packagesToScan);
+    Map<String, List<PropertyDescriptionData>> mapToAdd = propertyDescriptionsList.stream()
+      .sorted(Comparator.comparing(PropertyDescriptionData::getName))
+      .collect(Collectors.groupingBy(PropertyDescriptionData::getSource));
+    propertyDescriptions.putAll(mapToAdd);
+  }
+
+  private static ShipperConfigDescriptionDataHolder createShipperConfigDescriptions(List<String> shipperConfigPackagesToScan) {
+    final List<ShipperConfigDescriptionData> shipperConfigDescription = new ArrayList<>();
+    Reflections reflections = new Reflections(shipperConfigPackagesToScan, new FieldAnnotationsScanner());
+    Set<Field> fields = reflections.getFieldsAnnotatedWith(ShipperConfigElementDescription.class);
+    for (Field field : fields) {
+      ShipperConfigElementDescription description = field.getAnnotation(ShipperConfigElementDescription.class);
+      shipperConfigDescription.add(new ShipperConfigDescriptionData(description.path(), description.description(),
+        description.examples(), description.defaultValue()));
+    }
+    shipperConfigDescription.sort(Comparator.comparing(ShipperConfigDescriptionData::getPath));
+
+    final List<ShipperConfigDescriptionData> topLevelConfigSections = shipperConfigDescription.stream()
+      .filter(
+        s -> (s.getPath().equals("/filter") || s.getPath().equals("/input") || s.getPath().equals("/output")))
+      .distinct()
+      .collect(Collectors.toList());
+
+    final List<ShipperConfigDescriptionData> inputConfigSection = shipperConfigDescription.stream()
+      .filter(
+        s -> (s.getPath().startsWith("/input") && !s.getPath().equals("/input")))
+      .distinct()
+      .collect(Collectors.toList());
+
+    final List<ShipperConfigDescriptionData> filterConfigSection = shipperConfigDescription.stream()
+      .filter(
+        s -> (s.getPath().startsWith("/filter") && !s.getPath().equals("/filter") && !s.getPath().startsWith("/filter/[]/post_map_values")) || s.getPath().equals("/filter/[]/post_map_values"))
+      .distinct()
+      .collect(Collectors.toList());
+
+    final List<ShipperConfigDescriptionData> postMapValuesConfigSection = shipperConfigDescription.stream()
+      .filter(
+        s -> (s.getPath().startsWith("/filter/[]/post_map_values") && !s.getPath().equals("/filter/[]/post_map_values")))
+      .distinct()
+      .collect(Collectors.toList());
+
+    return new ShipperConfigDescriptionDataHolder(topLevelConfigSections, inputConfigSection, filterConfigSection, postMapValuesConfigSection);
+  }
+
+  private static List<PropertyDescriptionData> getPropertyDescriptions(List<String> packagesToScan) {
+    List<PropertyDescriptionData> result = new ArrayList<>();
+    for (String packageToScan : packagesToScan) {
+      Reflections reflections = new Reflections(packageToScan, new FieldAnnotationsScanner(), new MethodAnnotationsScanner());
+      Set<Field> fields = reflections.getFieldsAnnotatedWith(LogSearchPropertyDescription.class);
+      for (Field field : fields) {
+        LogSearchPropertyDescription propDescription = field.getAnnotation(LogSearchPropertyDescription.class);
+        for (String source : propDescription.sources()) {
+          result.add(new PropertyDescriptionData(propDescription.name(), propDescription.description(), propDescription.examples(), propDescription.defaultValue(), source));
+        }
+      }
+      Set<Method> methods = reflections.getMethodsAnnotatedWith(LogSearchPropertyDescription.class);
+      for (Method method : methods) {
+        LogSearchPropertyDescription propDescription = method.getAnnotation(LogSearchPropertyDescription.class);
+        for (String source : propDescription.sources()) {
+          result.add(new PropertyDescriptionData(propDescription.name(), propDescription.description(), propDescription.examples(), propDescription.defaultValue(), source));
+        }
+      }
+    }
+    return result;
+  }
+}
diff --git a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/model/response/PropertyDescriptionData.java b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/PropertyDescriptionData.java
similarity index 70%
rename from ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/model/response/PropertyDescriptionData.java
rename to ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/PropertyDescriptionData.java
index 6da8403..f1950dc 100644
--- a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/model/response/PropertyDescriptionData.java
+++ b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/PropertyDescriptionData.java
@@ -16,27 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ambari.logsearch.model.response;
+package org.apache.ambari.logsearch.doc;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
-public class PropertyDescriptionData {
+public class PropertyDescriptionData extends AbstractDescriptionData {
+
   private final String name;
-
-  private final String description;
-
-  private final String[] examples;
-
-  private final String defaultValue;
-
   @JsonIgnore
   private final String source;
 
   public PropertyDescriptionData(String name, String description, String[] examples, String defaultValue, String source) {
+    super(description, defaultValue, examples);
     this.name = name;
-    this.description = description;
-    this.examples = examples;
-    this.defaultValue = defaultValue;
     this.source = source;
   }
 
@@ -44,18 +36,6 @@
     return name;
   }
 
-  public String getDescription() {
-    return description;
-  }
-
-  public String[] getExamples() {
-    return examples;
-  }
-
-  public String getDefaultValue() {
-    return defaultValue;
-  }
-
   public String getSource() {
     return source;
   }
diff --git a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/model/response/ShipperConfigDescriptionData.java b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/ShipperConfigDescriptionData.java
similarity index 67%
rename from ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/model/response/ShipperConfigDescriptionData.java
rename to ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/ShipperConfigDescriptionData.java
index 91f7420..2afd3d1 100644
--- a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/model/response/ShipperConfigDescriptionData.java
+++ b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/ShipperConfigDescriptionData.java
@@ -16,37 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ambari.logsearch.model.response;
+package org.apache.ambari.logsearch.doc;
 
-public class ShipperConfigDescriptionData {
+public class ShipperConfigDescriptionData extends AbstractDescriptionData {
+
   private final String path;
 
-  private final String description;
-
-  private final String[] examples;
-
-  private final String defaultValue;
-
   public ShipperConfigDescriptionData(String path, String description, String[] examples, String defaultValue) {
+    super(description, defaultValue, examples);
     this.path = path;
-    this.description = description;
-    this.examples = examples;
-    this.defaultValue = defaultValue;
   }
 
   public String getPath() {
     return path;
   }
-
-  public String getDescription() {
-    return description;
-  }
-
-  public String[] getExamples() {
-    return examples;
-  }
-
-  public String getDefaultValue() {
-    return defaultValue;
-  }
 }
diff --git a/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/ShipperConfigDescriptionDataHolder.java b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/ShipperConfigDescriptionDataHolder.java
new file mode 100644
index 0000000..0a61e6a
--- /dev/null
+++ b/ambari-logsearch-docs/src/main/java/org/apache/ambari/logsearch/doc/ShipperConfigDescriptionDataHolder.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ambari.logsearch.doc;
+
+import java.util.List;
+
+public class ShipperConfigDescriptionDataHolder {
+  private final List<ShipperConfigDescriptionData> topLevelConfigSections;
+  private final List<ShipperConfigDescriptionData> inputConfigSections;
+  private final List<ShipperConfigDescriptionData> filterConfigSections;
+  private final List<ShipperConfigDescriptionData> postMapValuesConfigSections;
+
+  public ShipperConfigDescriptionDataHolder(List<ShipperConfigDescriptionData> topLevelConfigSections,
+                                            List<ShipperConfigDescriptionData> inputConfigSections,
+                                            List<ShipperConfigDescriptionData> filterConfigSections,
+                                            List<ShipperConfigDescriptionData> postMapValuesConfigSections) {
+    this.topLevelConfigSections = topLevelConfigSections;
+    this.inputConfigSections = inputConfigSections;
+    this.filterConfigSections = filterConfigSections;
+    this.postMapValuesConfigSections = postMapValuesConfigSections;
+  }
+
+  public List<ShipperConfigDescriptionData> getTopLevelConfigSections() {
+    return topLevelConfigSections;
+  }
+
+  public List<ShipperConfigDescriptionData> getInputConfigSections() {
+    return inputConfigSections;
+  }
+
+  public List<ShipperConfigDescriptionData> getFilterConfigSections() {
+    return filterConfigSections;
+  }
+
+  public List<ShipperConfigDescriptionData> getPostMapValuesConfigSections() {
+    return postMapValuesConfigSections;
+  }
+}
diff --git a/ambari-logsearch-docs/src/main/resources/log4j2.xml b/ambari-logsearch-docs/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..a8694ce
--- /dev/null
+++ b/ambari-logsearch-docs/src/main/resources/log4j2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<Configuration>
+  <Loggers>
+    <Root level="fatal">
+    </Root>
+  </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/ambari-logsearch-docs/src/main/resources/templates/logfeeder_properties.md.ftl b/ambari-logsearch-docs/src/main/resources/templates/logfeeder_properties.md.ftl
new file mode 100644
index 0000000..653f604
--- /dev/null
+++ b/ambari-logsearch-docs/src/main/resources/templates/logfeeder_properties.md.ftl
@@ -0,0 +1,25 @@
+<!---
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+## Log Feeder Configurations
+
+| `Name` | `Description` | `Default` | `Examples` |
+|---|---|---|---|
+<#if logfeederProperties??>
+    <#list logfeederProperties as logfeederProperty>
+|`${logfeederProperty.name}`|${logfeederProperty.description}|${logfeederProperty.defaultValue}|${logfeederProperty.examples}|
+    </#list>
+</#if>
\ No newline at end of file
diff --git a/ambari-logsearch-docs/src/main/resources/templates/logsearch_properties.md.ftl b/ambari-logsearch-docs/src/main/resources/templates/logsearch_properties.md.ftl
new file mode 100644
index 0000000..8089fe9
--- /dev/null
+++ b/ambari-logsearch-docs/src/main/resources/templates/logsearch_properties.md.ftl
@@ -0,0 +1,25 @@
+<!---
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+## Log Search Configurations
+
+| `Name` | `Description` | `Default` | `Examples` |
+|---|---|---|---|
+<#if logsearchProperties??>
+    <#list logsearchProperties as logsearchProperty>
+|`${logsearchProperty.name}`|${logsearchProperty.description}|${logsearchProperty.defaultValue}|${logsearchProperty.examples}|
+    </#list>
+</#if>
\ No newline at end of file
diff --git a/ambari-logsearch-docs/src/main/resources/templates/shipper_configurations.md.ftl b/ambari-logsearch-docs/src/main/resources/templates/shipper_configurations.md.ftl
new file mode 100644
index 0000000..85a7f34
--- /dev/null
+++ b/ambari-logsearch-docs/src/main/resources/templates/shipper_configurations.md.ftl
@@ -0,0 +1,65 @@
+<!---
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+## Log Feeder Shipper Descriptor
+
+### Top Level Descriptor Sections
+
+| `Path` | `Description` | `Default` | `Examples` |
+|---|---|---|---|
+<#if shipperConfigs.topLevelSections??>
+    <#list shipperConfigs.topLevelSections as section>
+|`${section.path}`|${section.description}|${section.defaultValue}|${section.examples}|
+    </#list>
+</#if>
+|`/output`|A list of output descriptors|`{}`||
+
+### Input Descriptor Sections
+
+| `Path` | `Description` | `Default` | `Examples` |
+|---|---|---|---|
+<#if shipperConfigs.inputConfigSections??>
+    <#list shipperConfigs.inputConfigSections as section>
+|`${section.path}`|${section.description}|${section.defaultValue}|${section.examples}|
+    </#list>
+</#if>
+
+### Filter Descriptor Sections
+
+| `Path` | `Description` | `Default` | `Examples` |
+|---|---|---|---|
+<#if shipperConfigs.filterConfigSections??>
+    <#list shipperConfigs.filterConfigSections as section>
+|`${section.path}`|${section.description}|${section.defaultValue}|${section.examples}|
+    </#list>
+</#if>
+
+### Mapper Descriptor Sections
+
+| `Path` | `Description` | `Default` | `Examples` |
+|---|---|---|---|
+<#if shipperConfigs.postMapValuesConfigSections??>
+    <#list shipperConfigs.postMapValuesConfigSections as section>
+|`${section.path}`|${section.description}|${section.defaultValue}|${section.examples}|
+    </#list>
+</#if>
+
+### Output Descriptor Sections
+
+| `Path` | `Description` | `Default` | `Examples` |
+|---|---|---|---|
+|`/output/[]/is_enabled`|A flag to show if the output should be used.|true|<ul><li>`true`</li><li>`false`</li></ul>|
\ No newline at end of file
diff --git a/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/LogFeederProps.java b/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/LogFeederProps.java
index 3be62ae..3c6c42f 100644
--- a/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/LogFeederProps.java
+++ b/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/LogFeederProps.java
@@ -91,7 +91,7 @@
     description = "Use implicit routing for Solr Collections.",
     examples = {"true"},
     defaultValue = "false",
-    sources = {LogFeederConstants.SOLR_IMPLICIT_ROUTING_PROPERTY}
+    sources = {LogFeederConstants.LOGFEEDER_PROPERTIES_FILE}
   )
   @Value("${"+ LogFeederConstants.SOLR_IMPLICIT_ROUTING_PROPERTY + ":false}")
   private boolean solrImplicitRouting;
@@ -245,7 +245,7 @@
     description = "Option to support sending logs to cloud storage. You can choose between supporting only cloud storage, non-cloud storage or both",
     examples = {"default", "cloud", "hybrid"},
     defaultValue = "default",
-    sources = {LogFeederConstants.CLOUD_STORAGE_MODE}
+    sources = {LogFeederConstants.LOGFEEDER_PROPERTIES_FILE}
   )
   @Value("${" + LogFeederConstants.CLOUD_STORAGE_MODE + ":default}")
   public LogFeederMode cloudStorageMode;
@@ -255,7 +255,7 @@
     description = "Type of storage that is the destination for cloud output logs.",
     examples = {"hdfs", "s3", "gcs", "adls", "wasb", "none"},
     defaultValue = "none",
-    sources = {LogFeederConstants.CLOUD_STORAGE_DESTINATION}
+    sources = {LogFeederConstants.LOGFEEDER_PROPERTIES_FILE}
   )
   @Value("${" + LogFeederConstants.CLOUD_STORAGE_DESTINATION + ":none}")
   private CloudStorageDestination cloudStorageDestination;
diff --git a/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/output/S3OutputConfig.java b/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/output/S3OutputConfig.java
index 465c2bd..3b689ca 100644
--- a/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/output/S3OutputConfig.java
+++ b/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/conf/output/S3OutputConfig.java
@@ -146,8 +146,7 @@
 
   @LogSearchPropertyDescription(
     name = LogFeederConstants.S3_MULTIOBJECT_DELETE_ENABLE,
-    description = "When enabled, multiple single-object delete requests are replaced by\n" +
-      "    a single 'delete multiple objects'-request, reducing the number of requests.",
+    description = "When enabled, multiple single-object delete requests are replaced by a single 'delete multiple objects'-request, reducing the number of requests.",
     defaultValue = "true",
     examples = {"false"},
     sources = {LogFeederConstants.LOGFEEDER_PROPERTIES_FILE}
diff --git a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/common/PropertyDescriptionStorage.java b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/common/PropertyDescriptionStorage.java
deleted file mode 100644
index bb40a91..0000000
--- a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/common/PropertyDescriptionStorage.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.ambari.logsearch.common;
-
-import org.apache.ambari.logsearch.config.api.LogSearchPropertyDescription;
-import org.apache.ambari.logsearch.model.response.PropertyDescriptionData;
-import org.reflections.Reflections;
-import org.reflections.scanners.FieldAnnotationsScanner;
-import org.reflections.scanners.MethodAnnotationsScanner;
-import org.springframework.beans.factory.annotation.Value;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Named;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-import static org.apache.ambari.logsearch.common.LogSearchConstants.LOGSEARCH_PROPERTIES_FILE;
-
-@Named
-public class PropertyDescriptionStorage {
-
-  private final Map<String, List<PropertyDescriptionData>> propertyDescriptions = new ConcurrentHashMap<>();
-
-  @Value("#{'${logsearch.doc.scan.prop.packages:org.apache.ambari.logsearch,org.apache.ambari.logfeeder}'.split(',')}")
-  @LogSearchPropertyDescription(
-    name = "logsearch.doc.scan.prop.packages",
-    description = "Comma separated list of packages for scanning @LogSearchPropertyDescription annotations.",
-    examples = {"org.apache.ambari.logsearch.mypackage"},
-    defaultValue = "org.apache.ambari.logsearch,org.apache.ambari.logfeeder",
-    sources = {LOGSEARCH_PROPERTIES_FILE}
-  )
-  private List<String> packagesToScan;
-
-  @PostConstruct
-  public void postConstruct() {
-    Thread loadPropertyDescriptionsThread = new Thread("load_property_descriptions") {
-      @Override
-      public void run() {
-        fillPropertyDescriptions();
-      }
-    };
-    loadPropertyDescriptionsThread.setDaemon(true);
-    loadPropertyDescriptionsThread.start();
-  }
-
-  public Map<String, List<PropertyDescriptionData>> getPropertyDescriptions() {
-    return propertyDescriptions;
-  }
-
-  private void fillPropertyDescriptions() {
-    List<PropertyDescriptionData> propertyDescriptionsList = getPropertyDescriptions(packagesToScan);
-    Map<String, List<PropertyDescriptionData>> mapToAdd = propertyDescriptionsList.stream()
-      .sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
-      .collect(Collectors.groupingBy(PropertyDescriptionData::getSource));
-    propertyDescriptions.putAll(mapToAdd);
-  }
-
-  private List<PropertyDescriptionData> getPropertyDescriptions(List<String> packagesToScan) {
-    List<PropertyDescriptionData> result = new ArrayList<>();
-    for (String packageToScan : packagesToScan) {
-      Reflections reflections = new Reflections(packageToScan, new FieldAnnotationsScanner(), new MethodAnnotationsScanner());
-      Set<Field> fields = reflections.getFieldsAnnotatedWith(LogSearchPropertyDescription.class);
-      for (Field field : fields) {
-        LogSearchPropertyDescription propDescription = field.getAnnotation(LogSearchPropertyDescription.class);
-        for (String source : propDescription.sources()) {
-          result.add(new PropertyDescriptionData(propDescription.name(), propDescription.description(), propDescription.examples(), propDescription.defaultValue(), source));
-        }
-      }
-      Set<Method> methods = reflections.getMethodsAnnotatedWith(LogSearchPropertyDescription.class);
-      for (Method method : methods) {
-        LogSearchPropertyDescription propDescription = method.getAnnotation(LogSearchPropertyDescription.class);
-        for (String source : propDescription.sources()) {
-          result.add(new PropertyDescriptionData(propDescription.name(), propDescription.description(), propDescription.examples(), propDescription.defaultValue(), source));
-        }
-      }
-    }
-    return result;
-  }
-}
diff --git a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/common/ShipperConfigDescriptionStorage.java b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/common/ShipperConfigDescriptionStorage.java
deleted file mode 100644
index accf11a..0000000
--- a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/common/ShipperConfigDescriptionStorage.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.ambari.logsearch.common;
-
-import org.apache.ambari.logsearch.config.api.ShipperConfigElementDescription;
-import org.apache.ambari.logsearch.model.response.ShipperConfigDescriptionData;
-import org.reflections.Reflections;
-import org.reflections.scanners.FieldAnnotationsScanner;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Named;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-@Named
-public class ShipperConfigDescriptionStorage {
-
-  private static final String SHIPPER_CONFIG_PACKAGE = "org.apache.ambari.logsearch.config.json.model.inputconfig.impl";
-  
-  private final List<ShipperConfigDescriptionData> shipperConfigDescription = new ArrayList<>();
-
-  @PostConstruct
-  public void postConstruct() {
-    Thread loadShipperConfigDescriptionThread = new Thread("load_shipper_config_description") {
-      @Override
-      public void run() {
-        fillShipperConfigDescriptions();
-      }
-    };
-    loadShipperConfigDescriptionThread.setDaemon(true);
-    loadShipperConfigDescriptionThread.start();
-  }
-
-  public List<ShipperConfigDescriptionData> getShipperConfigDescription() {
-    return shipperConfigDescription;
-  }
-
-  private void fillShipperConfigDescriptions() {
-    Reflections reflections = new Reflections(SHIPPER_CONFIG_PACKAGE, new FieldAnnotationsScanner());
-    Set<Field> fields = reflections.getFieldsAnnotatedWith(ShipperConfigElementDescription.class);
-    for (Field field : fields) {
-      ShipperConfigElementDescription description = field.getAnnotation(ShipperConfigElementDescription.class);
-      shipperConfigDescription.add(new ShipperConfigDescriptionData(description.path(), description.description(),
-          description.examples(), description.defaultValue()));
-    }
-    
-    shipperConfigDescription.sort((o1, o2) -> o1.getPath().compareTo(o2.getPath()));
-  }
-}
diff --git a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/doc/DocConstants.java b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/doc/DocConstants.java
index 8301bb0..49f5858 100644
--- a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/doc/DocConstants.java
+++ b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/doc/DocConstants.java
@@ -108,9 +108,6 @@
     public static final String GET_FEATURES_LIST = "Get features list.";
     public static final String GET_APP_DETAILS_OD = "Get application details.";
     public static final String GET_AUTH_DETAILS_OD = "Get authentication details.";
-    public static final String GET_ALL_PROPERTIES_INFO_OD = "List all available properties for Log Search and Log Feeder";
-    public static final String GET_LOGSEARCH_PROPERTIES_INFO_OD = "List all available properties for Log Search property file (e.g: logsearch.properties/logfeeder.properties)";
-    public static final String GET_ALL_SHIPPER_CONFIG_INFO_OD = "List all available shipper configuration element";
   }
 
   public class MetadataDescriptions {
diff --git a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/manager/InfoManager.java b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/manager/InfoManager.java
index 687bf0b..12ca598 100644
--- a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/manager/InfoManager.java
+++ b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/manager/InfoManager.java
@@ -20,16 +20,11 @@
 package org.apache.ambari.logsearch.manager;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.ambari.logsearch.common.LogSearchConstants;
 import org.apache.ambari.logsearch.conf.AuthPropsConfig;
-import org.apache.ambari.logsearch.common.PropertyDescriptionStorage;
-import org.apache.ambari.logsearch.common.ShipperConfigDescriptionStorage;
 import org.apache.ambari.logsearch.conf.LogSearchConfigApiConfig;
-import org.apache.ambari.logsearch.model.response.PropertyDescriptionData;
-import org.apache.ambari.logsearch.model.response.ShipperConfigDescriptionData;
 import org.springframework.beans.factory.annotation.Value;
 
 import javax.inject.Inject;
@@ -53,12 +48,6 @@
   @Inject
   private LogSearchConfigApiConfig logSearchConfigApiConfig;
 
-  @Inject
-  private PropertyDescriptionStorage propertyDescriptionStore;
-
-  @Inject
-  private ShipperConfigDescriptionStorage shipperConfigDescriptionStore;
-
   public Map<String, String> getApplicationInfo() {
     Map<String, String> appMap = new HashMap<>();
     appMap.put("application.version", logsearchAppVersion);
@@ -85,16 +74,4 @@
     featuresMap.put(LogSearchConstants.LOG_LEVEL_FILTERS_KEY, logLevelFiltersEnabled);
     return featuresMap;
   }
-
-  public Map<String, List<PropertyDescriptionData>> getPropertyDescriptions() {
-    return propertyDescriptionStore.getPropertyDescriptions();
-  }
-
-  public List<PropertyDescriptionData> getLogSearchPropertyDescriptions(String propertiesFile) {
-    return getPropertyDescriptions().get(propertiesFile);
-  }
-  
-  public List<ShipperConfigDescriptionData> getLogSearchShipperConfigDescription() {
-    return shipperConfigDescriptionStore.getShipperConfigDescription();
-  }
 }
diff --git a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/rest/InfoResource.java b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/rest/InfoResource.java
index 52ecdca..6fdb5eb 100644
--- a/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/rest/InfoResource.java
+++ b/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/rest/InfoResource.java
@@ -22,24 +22,17 @@
 import javax.inject.Named;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.ambari.logsearch.manager.InfoManager;
-import org.apache.ambari.logsearch.model.response.PropertyDescriptionData;
-import org.apache.ambari.logsearch.model.response.ShipperConfigDescriptionData;
 import org.springframework.context.annotation.Scope;
 
-import java.util.List;
 import java.util.Map;
 
-import static org.apache.ambari.logsearch.doc.DocConstants.PublicOperationDescriptions.GET_ALL_PROPERTIES_INFO_OD;
-import static org.apache.ambari.logsearch.doc.DocConstants.PublicOperationDescriptions.GET_ALL_SHIPPER_CONFIG_INFO_OD;
 import static org.apache.ambari.logsearch.doc.DocConstants.PublicOperationDescriptions.GET_APP_DETAILS_OD;
 import static org.apache.ambari.logsearch.doc.DocConstants.PublicOperationDescriptions.GET_FEATURES_LIST;
-import static org.apache.ambari.logsearch.doc.DocConstants.PublicOperationDescriptions.GET_LOGSEARCH_PROPERTIES_INFO_OD;
 import static org.apache.ambari.logsearch.doc.DocConstants.PublicOperationDescriptions.GET_AUTH_DETAILS_OD;
 
 @Api(value = "info", description = "General configuration information")
@@ -59,22 +52,6 @@
   }
 
   @GET
-  @Path("/properties")
-  @Produces({"application/json"})
-  @ApiOperation(GET_ALL_PROPERTIES_INFO_OD)
-  public Map<String, List<PropertyDescriptionData>> getPropertyDescriptions() {
-    return infoManager.getPropertyDescriptions();
-  }
-
-  @GET
-  @Path("/properties/{propertyFile}")
-  @Produces({"application/json"})
-  @ApiOperation(GET_LOGSEARCH_PROPERTIES_INFO_OD)
-  public List<PropertyDescriptionData> getPropertyFileDescription(@PathParam("propertyFile") String propertyFile) {
-    return infoManager.getLogSearchPropertyDescriptions(propertyFile);
-  }
-
-  @GET
   @Path("/features")
   @Produces({"application/json"})
   @ApiOperation(GET_FEATURES_LIST)
@@ -89,12 +66,4 @@
   public Map<String, Boolean> getAuthInfo() {
     return infoManager.getAuthMap();
   }
-
-  @GET
-  @Path("/shipperconfig")
-  @Produces({"application/json"})
-  @ApiOperation(GET_ALL_SHIPPER_CONFIG_INFO_OD)
-  public List<ShipperConfigDescriptionData> getShipperConfigDescription() {
-    return infoManager.getLogSearchShipperConfigDescription();
-  }
 }
diff --git a/docs/.keep b/docs/.keep
new file mode 100644
index 0000000..1924455
--- /dev/null
+++ b/docs/.keep
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 53d99b5..23a5d8e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,6 +44,7 @@
         <module>ambari-logsearch-logfeeder-container-registry</module>
         <module>ambari-logsearch-config-local</module>
         <module>ambari-logsearch-config-solr</module>
+        <module>ambari-logsearch-docs</module>
       </modules>
     </profile>
     <profile>
@@ -63,6 +64,7 @@
         <module>ambari-logsearch-logfeeder-container-registry</module>
         <module>ambari-logsearch-config-local</module>
         <module>ambari-logsearch-config-solr</module>
+        <module>ambari-logsearch-docs</module>
       </modules>
     </profile>
     <profile>