KNOX-1951 - Service Discovery Support for NiFi and NiFi Registry UI (#235)

diff --git a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/nifi/NifiRegistryServiceModelGenerator.java b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/nifi/NifiRegistryServiceModelGenerator.java
new file mode 100644
index 0000000..29766a9
--- /dev/null
+++ b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/nifi/NifiRegistryServiceModelGenerator.java
@@ -0,0 +1,87 @@
+/*
+ * 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.knox.gateway.topology.discovery.cm.model.nifi;
+
+import com.cloudera.api.swagger.client.ApiException;
+import com.cloudera.api.swagger.model.ApiConfigList;
+import com.cloudera.api.swagger.model.ApiRole;
+import com.cloudera.api.swagger.model.ApiService;
+import com.cloudera.api.swagger.model.ApiServiceConfig;
+import org.apache.knox.gateway.topology.discovery.cm.ServiceModel;
+import org.apache.knox.gateway.topology.discovery.cm.model.AbstractServiceModelGenerator;
+
+import java.util.Locale;
+
+public class NifiRegistryServiceModelGenerator extends AbstractServiceModelGenerator {
+
+  public static final String SERVICE = "NIFI-REGISTRY";
+  public static final String SERVICE_TYPE = "NIFIREGISTRY";
+  public static final String ROLE_TYPE = "NIFI_REGISTRY_SERVER";
+
+  /**
+   * @return The name of the Knox service for which the implementation will
+   * generate a model.
+   */
+  @Override
+  public String getService() {
+    return SERVICE;
+  }
+
+  /**
+   * @return The Cloudera Manager configuration service type.
+   */
+  @Override
+  public String getServiceType() {
+    return SERVICE_TYPE;
+  }
+
+  /**
+   * @return The Cloudera Manager configuration role type.
+   */
+  @Override
+  public String getRoleType() {
+    return ROLE_TYPE;
+  }
+
+  @Override
+  public ServiceModel.Type getModelType() {
+    return ServiceModel.Type.UI;
+  }
+
+  @Override
+  public ServiceModel generateService(ApiService service,
+      ApiServiceConfig serviceConfig, ApiRole role, ApiConfigList roleConfig)
+      throws ApiException {
+    String hostname = role.getHostRef().getHostname();
+    String scheme;
+    String port;
+    boolean sslEnabled = Boolean.parseBoolean(getRoleConfigValue(roleConfig, "ssl_enabled"));
+    if(sslEnabled) {
+      scheme = "https";
+      port = getRoleConfigValue(roleConfig, "nifi.registry.web.https.port");
+    } else {
+      scheme = "http";
+      port = getRoleConfigValue(roleConfig, "nifi.registry.web.http.port");
+    }
+    return new ServiceModel(getModelType(),
+        getService(),
+        getServiceType(),
+        getRoleType(),
+        String.format(Locale.getDefault(), "%s://%s:%s", scheme, hostname, port));
+  }
+}
diff --git a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/nifi/NifiServiceModelGenerator.java b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/nifi/NifiServiceModelGenerator.java
new file mode 100644
index 0000000..dcf26cf
--- /dev/null
+++ b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/nifi/NifiServiceModelGenerator.java
@@ -0,0 +1,87 @@
+/*
+ * 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.knox.gateway.topology.discovery.cm.model.nifi;
+
+import com.cloudera.api.swagger.client.ApiException;
+import com.cloudera.api.swagger.model.ApiConfigList;
+import com.cloudera.api.swagger.model.ApiRole;
+import com.cloudera.api.swagger.model.ApiService;
+import com.cloudera.api.swagger.model.ApiServiceConfig;
+import org.apache.knox.gateway.topology.discovery.cm.ServiceModel;
+import org.apache.knox.gateway.topology.discovery.cm.model.AbstractServiceModelGenerator;
+
+import java.util.Locale;
+
+public class NifiServiceModelGenerator extends AbstractServiceModelGenerator {
+
+  public static final String SERVICE = "NIFI";
+  public static final String SERVICE_TYPE = "NIFI";
+  public static final String ROLE_TYPE = "NIFI_NODE";
+
+  /**
+   * @return The name of the Knox service for which the implementation will
+   * generate a model.
+   */
+  @Override
+  public String getService() {
+    return SERVICE;
+  }
+
+  /**
+   * @return The Cloudera Manager configuration service type.
+   */
+  @Override
+  public String getServiceType() {
+    return SERVICE_TYPE;
+  }
+
+  /**
+   * @return The Cloudera Manager configuration role type.
+   */
+  @Override
+  public String getRoleType() {
+    return ROLE_TYPE;
+  }
+
+  @Override
+  public ServiceModel.Type getModelType() {
+    return ServiceModel.Type.UI;
+  }
+
+  @Override
+  public ServiceModel generateService(ApiService service,
+      ApiServiceConfig serviceConfig, ApiRole role, ApiConfigList roleConfig)
+      throws ApiException {
+    String hostname = role.getHostRef().getHostname();
+    String scheme;
+    String port;
+    boolean sslEnabled = Boolean.parseBoolean(getRoleConfigValue(roleConfig, "ssl_enabled"));
+    if(sslEnabled) {
+      scheme = "https";
+      port = getRoleConfigValue(roleConfig, "nifi.web.https.port");
+    } else {
+      scheme = "http";
+      port = getRoleConfigValue(roleConfig, "nifi.web.http.port");
+    }
+    return new ServiceModel(getModelType(),
+        getService(),
+        getServiceType(),
+        getRoleType(),
+        String.format(Locale.getDefault(), "%s://%s:%s", scheme, hostname, port));
+  }
+}
diff --git a/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator b/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator
index 8729e22..e6350ec 100644
--- a/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator
+++ b/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator
@@ -47,4 +47,6 @@
 org.apache.knox.gateway.topology.discovery.cm.model.zeppelin.ZeppelinServiceModelGenerator
 org.apache.knox.gateway.topology.discovery.cm.model.zeppelin.ZeppelinUIServiceModelGenerator
 org.apache.knox.gateway.topology.discovery.cm.model.zeppelin.ZeppelinWSServiceModelGenerator
+org.apache.knox.gateway.topology.discovery.cm.model.nifi.NifiServiceModelGenerator
+org.apache.knox.gateway.topology.discovery.cm.model.nifi.NifiRegistryServiceModelGenerator
 
diff --git a/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscoveryTest.java b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscoveryTest.java
index 7819c2d..2175596 100644
--- a/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscoveryTest.java
+++ b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscoveryTest.java
@@ -44,6 +44,8 @@
 import org.apache.knox.gateway.topology.discovery.cm.model.impala.ImpalaUIServiceModelGenerator;
 import org.apache.knox.gateway.topology.discovery.cm.model.kudu.KuduUIServiceModelGenerator;
 import org.apache.knox.gateway.topology.discovery.cm.model.livy.LivyServiceModelGenerator;
+import org.apache.knox.gateway.topology.discovery.cm.model.nifi.NifiRegistryServiceModelGenerator;
+import org.apache.knox.gateway.topology.discovery.cm.model.nifi.NifiServiceModelGenerator;
 import org.apache.knox.gateway.topology.discovery.cm.model.oozie.OozieServiceModelGenerator;
 import org.apache.knox.gateway.topology.discovery.cm.model.phoenix.PhoenixServiceModelGenerator;
 import org.apache.knox.gateway.topology.discovery.cm.model.ranger.RangerServiceModelGenerator;
@@ -515,6 +517,76 @@
     assertEquals(expectedURL, urls.get(0));
   }
 
+  @Test
+  public void testNiFiDiscovery() {
+    doTestNiFiDiscovery(false);
+  }
+
+  @Test
+  public void testNiFiDiscoverySSL() {
+    doTestNiFiDiscovery(true);
+  }
+
+  private void doTestNiFiDiscovery(boolean sslEnabled) {
+    final String hostName = "nifi-host";
+    final String port = "8080";
+    final String sslPort = "8443";
+    final String servicePort = sslEnabled ? "8443" : "8080";
+    final String expectedURL = (sslEnabled ? "https" : "http") + "://" + hostName + ":" + servicePort;
+
+    // Configure the role
+    Map<String, String> roleProperties = new HashMap<>();
+    roleProperties.put("nifi.web.http.port", port);
+    roleProperties.put("nifi.web.https.port", sslPort);
+    roleProperties.put("ssl_enabled", String.valueOf(sslEnabled));
+
+    ServiceDiscovery.Cluster cluster = doTestDiscovery(hostName,
+        "NIFI-1", NifiServiceModelGenerator.SERVICE_TYPE,
+        "nifi-NIFI_NODE-1",
+        NifiServiceModelGenerator.ROLE_TYPE,
+        Collections.emptyMap(),
+        roleProperties);
+
+    List<String> urls = cluster.getServiceURLs("NIFI");
+    assertEquals(1, urls.size());
+    assertEquals(expectedURL, urls.get(0));
+  }
+
+  @Test
+  public void testNiFiRegistryDiscovery() {
+    doTestNiFiRegistryDiscovery(false);
+  }
+
+  @Test
+  public void testNiFiRegistryDiscoverySSL() {
+    doTestNiFiRegistryDiscovery(true);
+  }
+
+  private void doTestNiFiRegistryDiscovery(boolean sslEnabled) {
+    final String hostName = "nifi-registry-host";
+    final String port = "18080";
+    final String sslPort = "18443";
+    final String servicePort = sslEnabled ? "18443" : "18080";
+    final String expectedURL = (sslEnabled ? "https" : "http") + "://" + hostName + ":" + servicePort;
+
+    // Configure the role
+    Map<String, String> roleProperties = new HashMap<>();
+    roleProperties.put("nifi.registry.web.http.port", port);
+    roleProperties.put("nifi.registry.web.https.port", sslPort);
+    roleProperties.put("ssl_enabled", String.valueOf(sslEnabled));
+
+    ServiceDiscovery.Cluster cluster = doTestDiscovery(hostName,
+        "NIFI_REGISTRY-1", NifiRegistryServiceModelGenerator.SERVICE_TYPE,
+        "NIFI_REGISTRY_SERVER-1",
+        NifiRegistryServiceModelGenerator.ROLE_TYPE,
+        Collections.emptyMap(),
+        roleProperties);
+
+    List<String> urls = cluster.getServiceURLs("NIFI-REGISTRY");
+    assertEquals(1, urls.size());
+    assertEquals(expectedURL, urls.get(0));
+  }
+
   private void doTestImpalaDiscovery(boolean sslEnabled) {
     final String hostName = "impalad-host";
     final String port     = "28000";
@@ -542,6 +614,7 @@
     assertEquals(expectedURL, urls.get(0));
   }
 
+
   private void doTestImpalaUIDiscovery(boolean sslEnabled, boolean webserverEnabled) {
     final String hostName = "impalad-host";
     final String port     = "25000";