Repository: ambari
Updated Branches:
  refs/heads/trunk 92c054b1d -> eca979132


http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/quicklinks/quicklinks.json
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/quicklinks/quicklinks.json
 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/quicklinks/quicklinks.json
new file mode 100644
index 0000000..74ea153
--- /dev/null
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/quicklinks/quicklinks.json
@@ -0,0 +1,40 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "protocol":
+    {
+      "type":"https",
+      "checks":[
+        {
+          "property":"ranger.service.https.attrib.ssl.enabled",
+          "desired":"true",
+          "site":"ranger-admin-site"
+        },
+        {
+          "property":"ranger.service.http.enabled",
+          "desired":"false",
+          "site":"ranger-admin-site"
+        }
+      ]
+    },
+
+    "links": [
+      {
+        "name": "ranger_admin_ui",
+        "label": "Ranger Admin UI",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@",
+        "template": "%@://%@:%@",
+        "port":{
+          "http_property": "http.service.port",
+          "http_default_port": "6080",
+          "https_property": "https.service.port",
+          "https_default_port": "6182",
+          "regex": "(\\d*)+",
+          "site": "ranger-site"
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/metainfo.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/metainfo.xml 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/metainfo.xml
index 2c9680c..2cf290b 100644
--- 
a/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/metainfo.xml
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/metainfo.xml
@@ -61,6 +61,12 @@
             <config-type>spark-thrift-sparkconf</config-type>
             <config-type>spark-hive-site-override</config-type>
           </configuration-dependencies>
+             <quickLinksConfigurations>
+                 <quickLinksConfiguration>
+                 <fileName>quicklinks.json</fileName>
+                 <default>true</default>
+               </quickLinksConfiguration>
+             </quickLinksConfigurations>
         </service>
     </services>
 </metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/quicklinks/quicklinks.json
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/quicklinks/quicklinks.json
 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/quicklinks/quicklinks.json
new file mode 100644
index 0000000..c3e51e6
--- /dev/null
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/SPARK/quicklinks/quicklinks.json
@@ -0,0 +1,28 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "protocol":
+    {
+      "type":"HTTP_ONLY"
+    },
+
+    "links": [
+      {
+        "name": "spark_history_server_ui",
+        "label": "Spark History Server UI",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@",
+        "template": "%@://%@:%@",
+        "port":{
+          "http_property": "spark.history.ui.port",
+          "http_default_port": "18080",
+          "https_property": "spark.history.ui.port",
+          "https_default_port": "18080",
+          "regex": "^(\\d+)$",
+          "site": "spark-defaults"
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/metainfo.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/metainfo.xml 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/metainfo.xml
index 5a21200..088bb16 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/metainfo.xml
@@ -50,6 +50,12 @@
           </packages>
         </osSpecific>
       </osSpecifics>
+      <quickLinksConfigurations>
+        <quickLinksConfiguration>
+          <fileName>quicklinks.json</fileName>
+          <default>true</default>
+        </quickLinksConfiguration>
+      </quickLinksConfigurations>
     </service>
 
     <service>
@@ -74,6 +80,13 @@
         </osSpecific>
       </osSpecifics>
       <configuration-dir>configuration-mapred</configuration-dir>
+      
<quickLinksConfigurations-dir>quicklinks-mapred</quickLinksConfigurations-dir>
+      <quickLinksConfigurations>
+        <quickLinksConfiguration>
+          <fileName>quicklinks.json</fileName>
+          <default>true</default>
+        </quickLinksConfiguration>
+      </quickLinksConfigurations>
     </service>
 
   </services>

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks-mapred/quicklinks.json
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks-mapred/quicklinks.json
 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks-mapred/quicklinks.json
new file mode 100644
index 0000000..993267d
--- /dev/null
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks-mapred/quicklinks.json
@@ -0,0 +1,80 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "protocol":
+    {
+      "type":"https",
+      "checks":[
+        {
+          "property":"mapreduce.jobhistory.http.policy",
+          "desired":"HTTPS_ONLY",
+          "site":"mapred-site"
+        }
+      ]
+    },
+
+    "links": [
+      {
+        "name": "jobhistory_ui",
+        "label": "JobHistory UI",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@",
+        "template": "%@://%@:%@",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name": "jobhistory_logs",
+        "label": "JobHistory logs",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@/logs",
+        "template": "%@://%@:%@/logs",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name":"jobhistory_jmx",
+        "label":"JobHistory JMX",
+        "requires_user_name":"false",
+        "url":"%@://%@:%@/jmx",
+        "template":"%@://%@/jmx",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name":"thread_stacks",
+        "label":"Thread Stacks",
+        "requires_user_name": "false",
+        "url":"%@://%@:%@/stacks",
+        "template":"%@://%@/stacks",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks/quicklinks.json
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks/quicklinks.json
 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks/quicklinks.json
new file mode 100644
index 0000000..3cf4c7f
--- /dev/null
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.3/services/YARN/quicklinks/quicklinks.json
@@ -0,0 +1,80 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "protocol":
+    {
+      "type":"https",
+      "checks":[
+        {
+          "property":"yarn.http.policy",
+          "desired":"HTTPS_ONLY",
+          "site":"yarn-site"
+        }
+      ]
+    },
+
+    "links": [
+      {
+        "name": "resourcemanager_ui",
+        "label": "ResourceManager UI",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@",
+        "template": "%@://%@:%@",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      },
+      {
+        "name": "resourcemanager_logs",
+        "label": "ResourceManager logs",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@/logs",
+        "template": "%@://%@:%@/logs",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      },
+      {
+        "name": "resourcemanager_jmx",
+        "label":"ResourceManager JMX",
+        "requires_user_name": "false",
+        "url":"%@://%@:%@/jmx",
+        "template":"%@://%@:%@/jmx",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      },
+      {
+        "name": "thread_stacks",
+        "label":"Thread Stacks",
+        "requires_user_name": "false",
+        "url":"%@://%@:%@/stacks",
+        "template":"%@://%@:%@/stacks",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/test/java/org/apache/ambari/server/api/resources/StackServiceResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/StackServiceResourceDefinitionTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/StackServiceResourceDefinitionTest.java
index 65f54d5..f398749 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/StackServiceResourceDefinitionTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/StackServiceResourceDefinitionTest.java
@@ -42,7 +42,7 @@ public class StackServiceResourceDefinitionTest {
     ResourceDefinition def = new StackServiceResourceDefinition();
 
     Set<SubResourceDefinition> subResources = def.getSubResourceDefinitions();
-    assertEquals(4, subResources.size());
+    assertEquals(5, subResources.size());
 
     boolean configReturned = false;
     boolean componentReturned = false;

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
new file mode 100644
index 0000000..8fcc76e
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
@@ -0,0 +1,128 @@
+/**
+ * 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.server.stack;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.state.quicklinks.Check;
+import org.apache.ambari.server.state.quicklinks.Link;
+import org.apache.ambari.server.state.quicklinks.Port;
+import org.apache.ambari.server.state.quicklinks.Protocol;
+import org.apache.ambari.server.state.quicklinks.QuickLinks;
+import org.apache.ambari.server.state.quicklinks.QuickLinksConfiguration;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class QuickLinksConfigurationModuleTest {
+
+  @Test
+  public void testResolveInherit() throws Exception{
+    QuickLinks[] results = resolveQuickLinks("parent_quicklinks.json", 
"child_quicklinks_to_inherit.json");
+    QuickLinks parentQuickLinks = results[0];
+    QuickLinks childQuickLinks = results[1];
+
+    //resolved quicklinks configuration
+    QuickLinksConfiguration childQuickLinksConfig = 
childQuickLinks.getQuickLinksConfiguration();
+    assertNotNull(childQuickLinksConfig);
+
+    //inherit links
+    List<Link> links = childQuickLinksConfig.getLinks();
+    assertNotNull(links);
+    assertEquals(4, links.size());
+    assertEquals(4, 
parentQuickLinks.getQuickLinksConfiguration().getLinks().size());
+
+    //inherit protocol
+    Protocol protocol = childQuickLinksConfig.getProtocol();
+    assertNotNull(protocol);
+    assertEquals("https", protocol.getType());
+    assertEquals(1, protocol.getChecks().size());
+  }
+
+  @Test
+  public void testResolveMerge() throws Exception {
+    QuickLinks[] results = resolveQuickLinks("parent_quicklinks.json", 
"child_quicklinks_to_merge.json");
+    QuickLinks parentQuickLinks = results[0];
+    QuickLinks childQuickLinks = results[1];
+
+    //resolved quicklinks configuration
+    QuickLinksConfiguration childQuickLinksConfig = 
childQuickLinks.getQuickLinksConfiguration();
+    assertNotNull(childQuickLinksConfig);
+
+    //merged links
+    List<Link> links = childQuickLinksConfig.getLinks();
+    assertNotNull(links);
+    assertEquals(7, links.size());
+    assertEquals(4, 
parentQuickLinks.getQuickLinksConfiguration().getLinks().size());
+  }
+
+  @Test
+  public void testResolveOverride() throws Exception{
+    QuickLinks[] results = resolveQuickLinks("parent_quicklinks.json", 
"child_quicklinks_to_override.json");
+    QuickLinks parentQuickLinks = results[0];
+    QuickLinks childQuickLinks = results[1];
+
+    //resolved quicklinks configuration
+    QuickLinksConfiguration childQuickLinksConfig = 
childQuickLinks.getQuickLinksConfiguration();
+    assertNotNull(childQuickLinksConfig);
+
+    //links
+    List<Link> links = childQuickLinksConfig.getLinks();
+    assertNotNull(links);
+    assertEquals(7, links.size());
+    assertEquals(4, 
parentQuickLinks.getQuickLinksConfiguration().getLinks().size());
+    boolean hasLink = false;
+    for(Link link: links){
+      String name = link.getName();
+      if("thread_stacks".equals(name)){
+        hasLink = true;
+        Port port = link.getPort();
+        assertEquals("mapred-site", port.getSite());
+      }
+    }
+    assertTrue(hasLink);
+
+    //protocol
+    Protocol protocol = childQuickLinksConfig.getProtocol();
+    assertNotNull(protocol);
+    assertEquals("http", protocol.getType());
+    assertEquals(3, protocol.getChecks().size());
+    List<Check> checks = protocol.getChecks();
+    for(Check check: checks){
+      assertEquals("mapred-site", check.getSite());
+    }
+  }
+
+  private QuickLinks[] resolveQuickLinks(String parentJson, String childJson) 
throws AmbariException{
+    File parentQuiclinksFile = new 
File(this.getClass().getClassLoader().getResource(parentJson).getFile());
+    File childQuickLinksFile = new 
File(this.getClass().getClassLoader().getResource(childJson).getFile());
+
+    QuickLinksConfigurationModule parentModule = new 
QuickLinksConfigurationModule(parentQuiclinksFile);
+    QuickLinksConfigurationModule childModule = new 
QuickLinksConfigurationModule(childQuickLinksFile);
+
+    childModule.resolve(parentModule, null, null);
+
+    QuickLinks parentQuickLinks = 
parentModule.getModuleInfo().getQuickLinksConfigurationMap().get(QuickLinksConfigurationModule.QUICKLINKS_CONFIGURATION_KEY);
+    QuickLinks childQuickLinks = 
childModule.getModuleInfo().getQuickLinksConfigurationMap().get(QuickLinksConfigurationModule.QUICKLINKS_CONFIGURATION_KEY);
+
+    return new QuickLinks[]{parentQuickLinks, childQuickLinks};
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/test/resources/child_quicklinks_to_inherit.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/child_quicklinks_to_inherit.json 
b/ambari-server/src/test/resources/child_quicklinks_to_inherit.json
new file mode 100644
index 0000000..40120cb
--- /dev/null
+++ b/ambari-server/src/test/resources/child_quicklinks_to_inherit.json
@@ -0,0 +1,7 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "links": []
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/test/resources/child_quicklinks_to_merge.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/child_quicklinks_to_merge.json 
b/ambari-server/src/test/resources/child_quicklinks_to_merge.json
new file mode 100644
index 0000000..819c400
--- /dev/null
+++ b/ambari-server/src/test/resources/child_quicklinks_to_merge.json
@@ -0,0 +1,65 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "protocol":
+    {
+      "type":"http",
+      "checks":[
+        {
+          "property":"mapreduce.jobhistory.http.policy",
+          "desired":"HTTP_ONLY",
+          "site":"mapred-site"
+        }
+      ]
+    },
+
+    "links": [
+      {
+        "name": "jobhistory_ui",
+        "label": "JobHistory UI",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@",
+        "template": "%@://%@:%@",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name": "jobhistory_logs",
+        "label": "JobHistory logs",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@/logs",
+        "template": "%@://%@:%@/logs",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name":"jobhistory_jmx",
+        "label":"JobHistory JMX",
+        "requires_user_name":"false",
+        "url":"%@://%@:%@/jmx",
+        "template":"%@://%@/jmx",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/test/resources/child_quicklinks_to_override.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/child_quicklinks_to_override.json 
b/ambari-server/src/test/resources/child_quicklinks_to_override.json
new file mode 100644
index 0000000..b042f98
--- /dev/null
+++ b/ambari-server/src/test/resources/child_quicklinks_to_override.json
@@ -0,0 +1,90 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "protocol":
+    {
+      "type":"http",
+      "checks":[
+        {
+          "property":"mapreduce.jobhistory.http.policy",
+          "desired":"HTTPS_ONLY",
+          "site":"mapred-site"
+        },
+        {
+          "property":"ssl.store.pach",
+          "desired":"EXIST",
+          "site":"mapred-site"
+        },
+        {
+          "property":"ssl.store.password",
+          "desired":"EXIST",
+          "site":"mapred-site"
+        }
+      ]
+    },
+
+    "links": [
+      {
+        "name": "jobhistory_ui",
+        "label": "JobHistory UI",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@",
+        "template": "%@://%@:%@",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name": "jobhistory_logs",
+        "label": "JobHistory logs",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@/logs",
+        "template": "%@://%@:%@/logs",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name":"jobhistory_jmx",
+        "label":"JobHistory JMX",
+        "requires_user_name":"false",
+        "url":"%@://%@:%@/jmx",
+        "template":"%@://%@/jmx",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      },
+      {
+        "name":"thread_stacks",
+        "label":"Thread Stacks",
+        "requires_user_name": "false",
+        "url":"%@://%@:%@/stacks",
+        "template":"%@://%@/stacks",
+        "port":{
+          "http_property": "mapreduce.jobhistory.webapp.address",
+          "http_default_port": "19888",
+          "https_property": "mapreduce.jobhistory.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "mapred-site"
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-server/src/test/resources/parent_quicklinks.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/parent_quicklinks.json 
b/ambari-server/src/test/resources/parent_quicklinks.json
new file mode 100644
index 0000000..3cf4c7f
--- /dev/null
+++ b/ambari-server/src/test/resources/parent_quicklinks.json
@@ -0,0 +1,80 @@
+{
+  "name": "default",
+  "description": "default quick links configuration",
+  "configuration": {
+    "protocol":
+    {
+      "type":"https",
+      "checks":[
+        {
+          "property":"yarn.http.policy",
+          "desired":"HTTPS_ONLY",
+          "site":"yarn-site"
+        }
+      ]
+    },
+
+    "links": [
+      {
+        "name": "resourcemanager_ui",
+        "label": "ResourceManager UI",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@",
+        "template": "%@://%@:%@",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      },
+      {
+        "name": "resourcemanager_logs",
+        "label": "ResourceManager logs",
+        "requires_user_name": "false",
+        "url": "%@://%@:%@/logs",
+        "template": "%@://%@:%@/logs",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      },
+      {
+        "name": "resourcemanager_jmx",
+        "label":"ResourceManager JMX",
+        "requires_user_name": "false",
+        "url":"%@://%@:%@/jmx",
+        "template":"%@://%@:%@/jmx",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      },
+      {
+        "name": "thread_stacks",
+        "label":"Thread Stacks",
+        "requires_user_name": "false",
+        "url":"%@://%@:%@/stacks",
+        "template":"%@://%@:%@/stacks",
+        "port":{
+          "http_property": "yarn.timeline-service.webapp.address",
+          "http_default_port": "8088",
+          "https_property": "yarn.timeline-service.webapp.https.address",
+          "https_default_port": "8090",
+          "regex": "\\w*:(\\d+)",
+          "site": "yarn-site"
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/assets/data/configurations/quicklinks.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/configurations/quicklinks.json 
b/ambari-web/app/assets/data/configurations/quicklinks.json
new file mode 100644
index 0000000..505a619
--- /dev/null
+++ b/ambari-web/app/assets/data/configurations/quicklinks.json
@@ -0,0 +1,102 @@
+{
+  "href" : 
"http://c6401.ambari.apache.org:8080/api/v1/stacks/HDP/versions/2.3/services/YARN/quicklinks?QuickLinkInfo/default=true&fields=*";,
+  "items" : [
+    {
+      "href" : 
"http://c6401.ambari.apache.org:8080/api/v1/stacks/HDP/versions/2.3/services/YARN/quicklinks/quicklinks.json";,
+      "QuickLinkInfo" : {
+        "default" : true,
+        "file_name" : "quicklinks.json",
+        "service_name" : "YARN",
+        "stack_name" : "HDP",
+        "stack_version" : "2.3",
+        "quicklink_data" : {
+          "QuickLinksConfiguration" : {
+            "description" : "default quick links configuration",
+            "name" : "default",
+            "configuration" : {
+              "protocol" : {
+                "type" : "https",
+                "checks" : [
+                  {
+                    "property" : "yarn.http.policy",
+                    "desired" : "HTTPS_ONLY",
+                    "site" : "yarn-site"
+                  }
+                ]
+              },
+              "links" : [
+                {
+                  "name" : "resourcemanager_ui",
+                  "label" : "ResourceManager UI",
+                  "url" : "%@://%@:%@",
+                  "template" : "%@://%@:%@",
+                  "port" : {
+                    "regex" : "\\w*:(\\d+)",
+                    "site" : "yarn-site",
+                    "http_property" : "yarn.timeline-service.webapp.address",
+                    "http_default_port" : "8088",
+                    "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                    "https_default_port" : "8090"
+                  },
+                  "removed" : false,
+                  "requires_user_name" : "false",
+                  "knox_url" : "%@://%@:%@/gatway/yarnui/yarn"
+                },
+                {
+                  "name" : "resourcemanager_logs",
+                  "label" : "ResourceManager logs",
+                  "url" : "%@://%@:%@/logs",
+                  "template" : "%@://%@:%@/logs",
+                  "port" : {
+                    "regex" : "\\w*:(\\d+)",
+                    "site" : "yarn-site",
+                    "http_property" : "yarn.timeline-service.webapp.address",
+                    "http_default_port" : "8088",
+                    "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                    "https_default_port" : "8090"
+                  },
+                  "removed" : false,
+                  "requires_user_name" : "false",
+                  "knox_url" : "%@://%@:%@/gatway/yarnui/yarn/logs"
+                },
+                {
+                  "name" : "resourcemanager_jmx",
+                  "label" : "ResourceManager JMX",
+                  "url" : "%@://%@:%@/jmx",
+                  "template" : "%@://%@:%@/jmx",
+                  "port" : {
+                    "regex" : "\\w*:(\\d+)",
+                    "site" : "yarn-site",
+                    "http_property" : "yarn.timeline-service.webapp.address",
+                    "http_default_port" : "8088",
+                    "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                    "https_default_port" : "8090"
+                  },
+                  "removed" : false,
+                  "requires_user_name" : "false",
+                  "knox_url" : "%@://%@:%@/gatway/yarnui/yarn/jmx"
+                },
+                {
+                  "name" : "thread_stacks",
+                  "label" : "Thread Stacks",
+                  "url" : "%@://%@:%@/stacks",
+                  "template" : "%@://%@:%@/stacks",
+                  "port" : {
+                    "regex" : "\\w*:(\\d+)",
+                    "site" : "yarn-site",
+                    "http_property" : "yarn.timeline-service.webapp.address",
+                    "http_default_port" : "8088",
+                    "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                    "https_default_port" : "8090"
+                  },
+                  "removed" : false,
+                  "knox_url" : "%@://%@:%@/gatway/yarnui/yarn/stacks"
+                }
+              ]
+            }
+          }
+        }
+      }
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/assets/data/configurations/quicklinks_services.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/configurations/quicklinks_services.json 
b/ambari-web/app/assets/data/configurations/quicklinks_services.json
new file mode 100644
index 0000000..27d5b91
--- /dev/null
+++ b/ambari-web/app/assets/data/configurations/quicklinks_services.json
@@ -0,0 +1,112 @@
+{
+  "href" : 
"http://c6401.ambari.apache.org:8080/api/v1/stacks/HDP/versions/2.3/services?StackServices/service_name.in(YARN)&quicklinks/QuickLinkInfo/default=true&fields=quicklinks/*",
+  "items" : [
+    {
+      "href" : 
"http://c6401.ambari.apache.org:8080/api/v1/stacks/HDP/versions/2.3/services/YARN";,
+      "StackServices" : {
+        "service_name" : "YARN",
+        "stack_name" : "HDP",
+        "stack_version" : "2.3"
+      },
+      "quicklinks" : [
+        {
+          "href" : 
"http://c6401.ambari.apache.org:8080/api/v1/stacks/HDP/versions/2.3/services/YARN/quicklinks/quicklinks.json";,
+          "QuickLinkInfo" : {
+            "default" : true,
+            "file_name" : "quicklinks.json",
+            "service_name" : "YARN",
+            "stack_name" : "HDP",
+            "stack_version" : "2.3",
+            "quicklink_data" : {
+              "QuickLinksConfiguration" : {
+                "description" : "default quick links configuration",
+                "name" : "default",
+                "configuration" : {
+                  "protocol" : {
+                    "type" : "https",
+                    "checks" : [
+                      {
+                        "property" : "yarn.http.policy",
+                        "desired" : "HTTPS_ONLY",
+                        "site" : "yarn-site"
+                      }
+                    ]
+                  },
+                  "links" : [
+                    {
+                      "name" : "resourcemanager_ui",
+                      "label" : "ResourceManager UI",
+                      "url" : "%@://%@:%@",
+                      "template" : "%@://%@:%@",
+                      "port" : {
+                        "regex" : "\\w*:(\\d+)",
+                        "site" : "yarn-site",
+                        "http_property" : 
"yarn.timeline-service.webapp.address",
+                        "http_default_port" : "8088",
+                        "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                        "https_default_port" : "8090"
+                      },
+                      "removed" : false,
+                      "requires_user_name" : "false",
+                      "knox_url" : "%@://%@:%@/gatway/yarnui/yarn"
+                    },
+                    {
+                      "name" : "resourcemanager_logs",
+                      "label" : "ResourceManager logs",
+                      "url" : "%@://%@:%@/logs",
+                      "template" : "%@://%@:%@/logs",
+                      "port" : {
+                        "regex" : "\\w*:(\\d+)",
+                        "site" : "yarn-site",
+                        "http_property" : 
"yarn.timeline-service.webapp.address",
+                        "http_default_port" : "8088",
+                        "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                        "https_default_port" : "8090"
+                      },
+                      "removed" : false,
+                      "requires_user_name" : "false",
+                      "knox_url" : "%@://%@:%@/gatway/yarnui/yarn/logs"
+                    },
+                    {
+                      "name" : "resourcemanager_jmx",
+                      "label" : "ResourceManager JMX",
+                      "url" : "%@://%@:%@/jmx",
+                      "template" : "%@://%@:%@/jmx",
+                      "port" : {
+                        "regex" : "\\w*:(\\d+)",
+                        "site" : "yarn-site",
+                        "http_property" : 
"yarn.timeline-service.webapp.address",
+                        "http_default_port" : "8088",
+                        "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                        "https_default_port" : "8090"
+                      },
+                      "removed" : false,
+                      "requires_user_name" : "false",
+                      "knox_url" : "%@://%@:%@/gatway/yarnui/yarn/jmx"
+                    },
+                    {
+                      "name" : "thread_stacks",
+                      "label" : "Thread Stacks",
+                      "url" : "%@://%@:%@/stacks",
+                      "template" : "%@://%@:%@/stacks",
+                      "port" : {
+                        "regex" : "\\w*:(\\d+)",
+                        "site" : "yarn-site",
+                        "http_property" : 
"yarn.timeline-service.webapp.address",
+                        "http_default_port" : "8088",
+                        "https_property" : 
"yarn.timeline-service.webapp.https.address",
+                        "https_default_port" : "8090"
+                      },
+                      "removed" : false,
+                      "knox_url" : "%@://%@:%@/gatway/yarnui/yarn/stacks"
+                    }
+                  ]
+                }
+              }
+            }
+          }
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/mappers.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers.js b/ambari-web/app/mappers.js
index 312128b..96193bc 100644
--- a/ambari-web/app/mappers.js
+++ b/ambari-web/app/mappers.js
@@ -26,6 +26,7 @@ require('mappers/configs/stack_config_properties_mapper');
 require('mappers/configs/config_groups_mapper');
 require('mappers/configs/service_config_version_mapper');
 require('mappers/repository_version_mapper');
+require('mappers/quicklinks_mapper');
 require('mappers/hosts_mapper');
 require('mappers/cluster_mapper');
 require('mappers/racks_mapper');

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/mappers/quicklinks_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/quicklinks_mapper.js 
b/ambari-web/app/mappers/quicklinks_mapper.js
new file mode 100644
index 0000000..6cb1fe0
--- /dev/null
+++ b/ambari-web/app/mappers/quicklinks_mapper.js
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+
+var App = require("app");
+
+App.quicklinksMapper = App.QuickDataMapper.create({
+  model: App.QuickLinksConfig,
+
+  config: {
+    "id": "QuickLinkInfo.service_name",
+    "file_name" : "QuickLinkInfo.file_name",
+    "service_name" : "QuickLinkInfo.service_name",
+    "stack_name" : "QuickLinkInfo.stack_name",
+    "stack_version" : "QuickLinkInfo.stack_version",
+    "name" : "QuickLinkInfo.quicklink_data.QuickLinksConfiguration.name",
+    "protocol" : 
"QuickLinkInfo.quicklink_data.QuickLinksConfiguration.configuration.protocol",
+    "links" : 
"QuickLinkInfo.quicklink_data.QuickLinksConfiguration.configuration.links"
+  },
+
+  map: function(json){
+    console.time('App.quicklinksMapper execution time');
+
+    var result = [];
+    var linkResult = [];
+
+    json.items.forEach(function(item) {
+      var parseResult = this.parseIt(item, this.get('config'));
+      console.log("parseResult", parseResult);
+      result.push(parseResult);
+    }, this);
+
+    App.store.loadMany(this.get('model'), result);
+    App.store.commit();
+    console.timeEnd('App.quicklinksMapper execution time');
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/models.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models.js b/ambari-web/app/models.js
index e1bceec..1f0a0ab 100644
--- a/ambari-web/app/models.js
+++ b/ambari-web/app/models.js
@@ -34,6 +34,7 @@ require('models/repository');
 require('models/stack_service');
 require('models/stack_service_component');
 require('models/quick_links');
+require('models/quicklinks/quick_links_config');
 require('models/service');
 require('models/service_audit');
 require('models/service/hdfs');

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/models/quicklinks/quick_links_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/quicklinks/quick_links_config.js 
b/ambari-web/app/models/quicklinks/quick_links_config.js
new file mode 100644
index 0000000..d7d98e2
--- /dev/null
+++ b/ambari-web/app/models/quicklinks/quick_links_config.js
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.QuickLinksConfig = DS.Model.extend({
+  //general information
+  name: DS.attr('string'),
+  description: DS.attr('string'),
+  fileName: DS.attr('string'),
+  serviceName: DS.attr('string'),
+  stackName: DS.attr('string'),
+  stackVersion: DS.attr('string'),
+  //protocol configurations
+  protocol: DS.attr('object'),
+  //links configurations
+  links: DS.attr('array')
+});
+
+App.QuickLinksConfig.FIXTURES = [];

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/templates/main/service/item.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/service/item.hbs 
b/ambari-web/app/templates/main/service/item.hbs
index ed989a1..9fba3e2 100644
--- a/ambari-web/app/templates/main/service/item.hbs
+++ b/ambari-web/app/templates/main/service/item.hbs
@@ -18,8 +18,8 @@
 
 {{view App.MainServiceInfoMenuView configTabBinding="view.hasConfigTab" 
heatmapTabBinding="view.hasHeatmapTab"}}
   <div class="span3 quick-links-wrapper">
-    {{#if view.service.quickLinks.length}}
-      {{#view App.QuickViewLinks contentBinding="view.service"}}
+    {{#view App.QuickViewLinks contentBinding="view.service"}}
+      {{#if view.hasQuickLinksConfiged}}
         <ul class="nav nav-pills move">
           <li class="dropdown quick-links-dropdown">
             <a class="dropdown-toggle" id="quick-links-dropdown-btn" 
data-toggle="dropdown" href="#">{{t common.quickLinks}}<b class="caret"></b></a>
@@ -52,8 +52,8 @@
            </ul>
           </li>
         </ul>
-      {{/view}}
-    {{/if}}
+      {{/if}}
+    {{/view}}
   </div>
 
 {{#isAuthorized "SERVICE.RUN_CUSTOM_COMMAND, SERVICE.RUN_SERVICE_CHECK, 
SERVICE.START_STOP, SERVICE.TOGGLE_MAINTENANCE, SERVICE.ENABLE_HA"}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax/ajax.js 
b/ambari-web/app/utils/ajax/ajax.js
index 71ee9db..54a659e 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -636,6 +636,18 @@ var urls = {
     'mock': '/data/configurations/theme_services.json'
   },
 
+  /*************************CONFIG 
QUICKLINKS****************************************/
+
+  'configs.quicklinksconfig': {
+    'real': 
'{stackVersionUrl}/services/{serviceName}/quicklinks?QuickLinkInfo/default=true&fields=*',
+    'mock': '/data/configurations/quicklinks.json'
+  },
+
+  'configs.quicklinksconfig.services': {
+    'real': 
'{stackVersionUrl}/services?StackServices/service_name.in({serviceNames})&quicklinks/QuickLinkInfo/default=true&fields=quicklinks/*',
+    'mock': '/data/configurations/quicklinks_services.json'
+  },
+
   /*************************CONFIG 
GROUPS***************************************/
 
   'configs.config_groups.load.all': {

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/app/views/common/quick_view_link_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/quick_view_link_view.js 
b/ambari-web/app/views/common/quick_view_link_view.js
index e2e8d46..e58e47f 100644
--- a/ambari-web/app/views/common/quick_view_link_view.js
+++ b/ambari-web/app/views/common/quick_view_link_view.js
@@ -23,6 +23,8 @@ App.QuickViewLinks = Em.View.extend({
 
   isLoaded: false,
 
+  hasQuickLinksConfiged: false,
+
   /**
    * service which has blank target of link
    * @type {Array}
@@ -54,7 +56,7 @@ App.QuickViewLinks = Em.View.extend({
   /**
    * list of files that contains properties for enabling/disabling ssl
    */
-  requiredSiteNames: ['hadoop-env', 'yarn-env', 'hbase-env', 'oozie-env', 
'mapred-env', 'storm-env', 'falcon-env', 'core-site', 'hdfs-site', 
'hbase-site', 'oozie-site', 'yarn-site', 'mapred-site', 'storm-site', 
'spark-defaults', 'accumulo-site', 'application-properties', 
'ranger-admin-site', 'ranger-site', 'admin-properties'],
+  requiredSiteNames: [],
 
   /**
    * @type {string}
@@ -74,13 +76,14 @@ App.QuickViewLinks = Em.View.extend({
   }.property().volatile(),
 
   didInsertElement: function () {
-    this.setQuickLinks();
+    this.loadQuickLinksConfigurations();
   },
 
   willDestroyElement: function () {
     this.get('configProperties').clear();
     this.get('actualTags').clear();
     this.get('quickLinks').clear();
+    this.get('requiredSiteNames').clear();
   },
 
   /**
@@ -137,6 +140,54 @@ App.QuickViewLinks = Em.View.extend({
     this.getQuickLinksHosts();
   },
 
+  loadQuickLinksConfigurations: function(){
+    var serviceName = this.get('content.serviceName');
+    console.info("Loading quicklinks configurations for " + serviceName);
+    return App.ajax.send({
+      name: 'configs.quicklinksconfig',
+      sender: this,
+      data: {
+        serviceName: serviceName,
+        stackVersionUrl: App.get('stackVersionURL')
+      },
+      success: 'loadQuickLinksConfigSuccessCallback'
+    });
+  },
+
+  loadQuickLinksConfigSuccessCallback: function(data){
+    App.quicklinksMapper.map(data);
+    var quickLinksConfig = this.getQuickLinksConfiguration();
+    if(quickLinksConfig != null){
+      var protocolConfig = Em.get(quickLinksConfig, 'protocol');
+      var checks = Em.get(protocolConfig, 'checks');
+      var sites = ['core-site', 'hdfs-site'];
+      if(checks){
+        checks.forEach(function(check){
+          var protocolConfigSiteProp = Em.get(check, 'site')
+          if (sites.indexOf(protocolConfigSiteProp) < 0){
+            sites.push(protocolConfigSiteProp);
+          }
+        }, this);
+      }
+
+      var links = Em.get(quickLinksConfig, 'links');
+      if(links && links.length > 0){
+        links.forEach(function(link){
+          if(!link.remove){
+            var portConfig = Em.get(link, 'port');
+            var portConfigSiteProp = Em.get(portConfig, 'site');
+            if(sites.indexOf(portConfigSiteProp) < 0){
+              sites.push(portConfigSiteProp);
+            }
+          }
+        }, this);
+
+        this.set('requiredSiteNames', sites);
+        this.setQuickLinks();
+      }
+    }
+  },
+
   /**
    * call for public host names
    * @returns {$.ajax}
@@ -157,8 +208,12 @@ App.QuickViewLinks = Em.View.extend({
   },
 
   setQuickLinksSuccessCallback: function (response) {
-    var hosts = this.getHosts(response, this.get('content.serviceName'));
-    if (hosts.length === 0 || Em.isNone(this.get('content.quickLinks'))) {
+    var serviceName = this.get('content.serviceName');
+    var hosts = this.getHosts(response, serviceName);
+    var hasQuickLinks = this.hasQuickLinksConfig(serviceName);
+    this.set('hasQuickLinksConfiged', hasQuickLinks); // no need to set 
quicklinks if current service does not have quick links configured...
+
+    if (hosts.length === 0){
       this.setEmptyLinks();
     } else if (hosts.length === 1) {
       this.setSingleHostLinks(hosts, response);
@@ -192,6 +247,73 @@ App.QuickViewLinks = Em.View.extend({
     return App.router.get('configurationController').getConfigsByTags(tags);
   },
 
+  getQuickLinksConfiguration: function(){
+    var serviceName =  this.get('content.serviceName');
+    var self = this;
+    if(self.hasQuickLinksConfig(serviceName)){
+      var quickLinksConfiguration = 
App.QuickLinksConfig.find().findProperty("id", serviceName);
+      return quickLinksConfiguration;
+    }
+    return null;
+  },
+
+  hasQuickLinksConfig: function(serviceName) {
+    var result = App.QuickLinksConfig.find().findProperty('id', serviceName);
+    if(!result)
+      return false;
+
+    var links = result.get("links");
+    if(links && links.length > 0){
+      var toBeRemoved = 0;
+      links.forEach(function(link){
+        if(link.remove)
+          toBeRemoved++;
+      });
+      return !(links.length  === toBeRemoved);
+    } else {
+      return false;
+    }
+  },
+
+  toAddLink: function(link){
+    var linkRemoved = Em.get(link, 'removed');
+    var template = Em.get(link, 'template');
+    return (template && !linkRemoved);
+  },
+
+  getHostLink: function(link, host, protocol, configProperties, response){
+    var serviceName = this.get('content.serviceName');
+    if (serviceName === 'MAPREDUCE2' && response) {
+      var portConfig = Em.get(link, 'port');
+      var siteName = Em.get(portConfig, 'site');
+      var siteConfigs = this.get('configProperties').findProperty('type', 
siteName).properties;
+      var hostPortConfigValue = siteConfigs[Em.get(portConfig, protocol + 
'_config')];
+      if (hostPortConfigValue != null) {
+        var hostPortValue = hostPortConfigValue.match(new 
RegExp("([\\w\\d.-]*):(\\d+)"));
+        var hostObj = response.items.findProperty('Hosts.host_name', 
hostPortValue[1]);
+        if (hostObj != null) {
+          host = hostObj.Hosts.public_host_name;
+        }
+      }
+    }
+
+    var linkPort = this.setPort(Em.get(link, 'port'), protocol, 
configProperties);
+    if (this.toAddLink(link)) {
+      var newItem = {};
+      var requiresUserName = Em.get(link, 'requires_user_name');
+      var template = Em.get(link, 'template');
+        if('true' === requiresUserName){
+          newItem.url = template.fmt(protocol, host, linkPort, 
App.router.get('loginName'));
+        } else {
+          newItem.url = template.fmt(protocol, host, linkPort);
+        }
+        newItem.label = link.label;
+        return newItem;
+    } else {
+      return null;
+    }
+  },
+
   /**
    * set empty links
    */
@@ -209,42 +331,26 @@ App.QuickViewLinks = Em.View.extend({
    * @param {Array} hosts
    */
   setSingleHostLinks: function (hosts, response) {
-    var quickLinks = this.get('content.quickLinks').map(function (item) {
-      var protocol = this.setProtocol(item.get('serviceName'), 
this.get('configProperties'), this.get('ambariProperties'), item);
+    var quickLinksConfig = this.getQuickLinksConfiguration();
+    if(quickLinksConfig != null){
+      var quickLinks = [];
+      var configProperties = this.get('configProperties');
+      var protocol = this.setProtocol(configProperties, quickLinksConfig);
       var publicHostName = hosts[0].publicHostName;
-      var port = item.get('http_config') && this.setPort(item, protocol);
-      var siteConfigs = {};
-
-      if (item.get('template')) {
-        if (item.get('serviceName') === 'MAPREDUCE2') {
-          siteConfigs = this.get('configProperties').findProperty('type', 
item.get('site')).properties;
-          var hostPortConfigValue = siteConfigs[item.get(protocol + 
'_config')];
-          if (hostPortConfigValue != null) {
-            var hostPortValue = hostPortConfigValue.match(new 
RegExp("([\\w\\d.-]*):(\\d+)"));
-            var hostObj = response.items.findProperty('Hosts.host_name', 
hostPortValue[1]);
-            if (hostObj != null) {
-              var publicHostValue = hostObj.Hosts.public_host_name;
-              hostPortConfigValue = "%@:%@".fmt(publicHostValue, 
hostPortValue[2])
-            }
-          }
-          item.set('url', item.get('template').fmt(protocol, 
hostPortConfigValue));
-        } else if (item.get('serviceName') === 'RANGER') {
-          siteConfigs = this.get('configProperties').findProperty('type', 
'admin-properties').properties;
-          if (siteConfigs['policymgr_external_url']) {
-            // external_url example: "http://c6404.ambari.apache.org:6080";
-            var hostAndPort = 
siteConfigs['policymgr_external_url'].split('://')[1];
-            item.set('url', protocol + '://' + hostAndPort);
-          } else {
-            item.set('url', item.get('template').fmt(protocol, publicHostName, 
port));
-          }
-        } else {
-          item.set('url', item.get('template').fmt(protocol, publicHostName, 
port, App.router.get('loginName')));
+
+      var links = Em.get(quickLinksConfig, 'links');
+      links.forEach(function(link){
+        var newItem = this.getHostLink(link, publicHostName, protocol, 
configProperties, response); //quicklink generated for the hbs template
+        if(newItem != null){
+          quickLinks.push(newItem);
         }
-      }
-      return item;
-    }, this);
-    this.set('quickLinks', quickLinks);
-    this.set('isLoaded', true);
+      }, this);
+      this.set('quickLinks', quickLinks);
+      this.set('isLoaded', true);
+    } else {
+      this.set('quickLinks', []);
+      this.set('isLoaded', false);
+    }
   },
 
   /**
@@ -252,18 +358,31 @@ App.QuickViewLinks = Em.View.extend({
    * @param {Array} hosts
    */
   setMultipleHostLinks: function (hosts) {
+    var quickLinksConfig = this.getQuickLinksConfiguration();
+    if(quickLinksConfig == null){
+      this.set('quickLinksArray', []);
+      this.set('isLoaded', false);
+      return;
+    }
+
     var quickLinksArray = [];
     hosts.forEach(function (host) {
+      var publicHostName = host.publicHostName;
       var quickLinks = [];
-      this.get('content.quickLinks').forEach(function (item) {
-        var newItem = {};
-        var protocol = this.setProtocol(item.get('serviceName'), 
this.get('configProperties'), this.get('ambariProperties'), item);
-        if (item.get('template')) {
+      var configProperties = this.get('configProperties');
+
+      var protocol = this.setProtocol(configProperties, quickLinksConfig);
+      var serviceName = Em.get(quickLinksConfig, 'serviceName');
+      var links = Em.get(quickLinksConfig, 'links');
+      links.forEach(function(link){
+        var linkRemoved = Em.get(link, 'removed');
+        var template = Em.get(link, 'template');
+        if (template && !linkRemoved) {
           var port;
           var hostNameRegExp = new RegExp('([\\w\\W]*):\\d+');
-          if (item.get('serviceName') === 'HDFS') {
+          if (serviceName === 'HDFS') {
             var config;
-            var configPropertiesObject = 
this.get('configProperties').findProperty('type', item.get('site'));
+            var configPropertiesObject = configProperties.findProperty('type', 
'hdfs-site');
             if (configPropertiesObject && configPropertiesObject.properties) {
               var properties = configPropertiesObject.properties;
               var nameServiceId = properties['dfs.nameservices'];
@@ -280,19 +399,18 @@ App.QuickViewLinks = Em.View.extend({
                 }
               }
             }
-            port = this.setPort(item, protocol, config);
-          } else {
-            port = item.get('http_config') && this.setPort(item, protocol);
+            var portConfig = Em.get(link, 'port');
+            Em.set(portConfig, protocol +'_property', config);
+            Em.set(link, 'port', portConfig)
           }
-          if (item.get('serviceName') === 'OOZIE') {
-            newItem.url = item.get('template').fmt(protocol, 
host.publicHostName, port, App.router.get('loginName'));
-          } else {
-            newItem.url = item.get('template').fmt(protocol, 
host.publicHostName, port);
+
+          var newItem = this.getHostLink(link, publicHostName, protocol, 
configProperties); //quicklink generated for the hbs template
+          if(newItem != null){
+            quickLinks.push(newItem);
           }
-          newItem.label = item.get('label');
         }
-        quickLinks.push(newItem);
       }, this);
+
       if (host.status) {
         quickLinks.set('publicHostNameLabel', 
Em.I18n.t('quick.links.publicHostName').format(host.publicHostName, 
host.status));
       } else {
@@ -456,6 +574,31 @@ App.QuickViewLinks = Em.View.extend({
    */
   servicesSupportsHttps: ["HDFS", "HBASE"],
 
+  reverseType: function(type){
+    if("https" === type)
+      return "http";
+    else if("http" === type)
+      return "https"
+  },
+
+  meetDesired: function(configProperties, configType, property, desiredState){
+    var currentConfig = configProperties.findProperty('type', configType);
+    var currentPropertyValue = currentConfig.properties[property];
+    if("NOT_EXIST" === desiredState){
+      if(currentPropertyValue == null)
+        return true;
+      else
+        return false
+    } else if("EXIST" === desiredState){
+      if(currentPropertyValue == null)
+        return false;
+      else
+        return true;
+    } else {
+      return (desiredState === currentPropertyValue)
+    }
+  },
+
   /**
    * setProtocol - if cluster is secure for some services (GANGLIA, 
MAPREDUCE2, YARN and servicesSupportsHttps)
    * protocol becomes "https" otherwise "http" (by default)
@@ -466,95 +609,51 @@ App.QuickViewLinks = Em.View.extend({
    * @method setProtocol
    * @param item
    */
-  setProtocol: function (serviceName, configProperties, ambariProperties, 
item) {
+  setProtocol: function (configProperties, item) {
     var hadoopSslEnabled = false;
+
     if (configProperties && configProperties.length > 0) {
       var hdfsSite = configProperties.findProperty('type', 'hdfs-site');
       hadoopSslEnabled = (hdfsSite && Em.get(hdfsSite, 'properties') && 
hdfsSite.properties['dfs.http.policy'] === 'HTTPS_ONLY');
     }
-    switch (serviceName) {
-      case "YARN":
-        var yarnProperties = configProperties && 
configProperties.findProperty('type', 'yarn-site');
-        if (yarnProperties && yarnProperties.properties) {
-          if (yarnProperties.properties['yarn.http.policy'] === 'HTTPS_ONLY') {
-            return "https";
-          } else if (yarnProperties.properties['yarn.http.policy'] === 
'HTTP_ONLY') {
-            return "http";
-          }
-        }
-        return hadoopSslEnabled ? "https" : "http";
-        break;
-      case "MAPREDUCE2":
-        var mapred2Properties = configProperties && 
configProperties.findProperty('type', 'mapred-site');
-        if (mapred2Properties && mapred2Properties.properties) {
-          if (mapred2Properties.properties['mapreduce.jobhistory.http.policy'] 
=== 'HTTPS_ONLY') {
-            return "https";
-          } else if 
(mapred2Properties.properties['mapreduce.jobhistory.http.policy'] === 
'HTTP_ONLY') {
-            return "http";
-          }
-        }
-        return hadoopSslEnabled ? "https" : "http";
-        break;
-      case "ACCUMULO":
-        var accumuloProperties = configProperties && 
configProperties.findProperty('type', 'accumulo-site');
-        if (accumuloProperties && accumuloProperties.properties) {
-          if (accumuloProperties.properties['monitor.ssl.keyStore'] && 
accumuloProperties.properties['monitor.ssl.trustStore']) {
-            return "https";
-          } else {
-            return "http";
-          }
-        }
-        return "http";
-        break;
-      case "ATLAS":
-        var atlasProperties = configProperties && 
configProperties.findProperty('type', 'application-properties');
-        if (atlasProperties && atlasProperties.properties) {
-          if (atlasProperties.properties['metadata.enableTLS'] == "true") {
-            return "https";
-          } else {
-            return "http";
-          }
-        }
+
+    var protocolConfig = Em.get(item, 'protocol');
+    if(!protocolConfig){
+      if(hadoopSslEnabled)
+        return "https";
+      else
         return "http";
-        break;
-      case "OOZIE":
-        var site = configProperties.findProperty('type', 'oozie-site');
-        var properties = site && site.properties;
-        var url = properties && properties['oozie.base.url'];
-        var re = new RegExp(item.get('regex'));
-        var portValue = url && url.match(re);
-        var port = portValue && portValue.length && portValue[1];
-        var protocol = 'http';
-        var isHttpsPropertiesEnabled = properties && 
(properties['oozie.https.port'] ||
-                                                      
properties['oozie.https.keystore.file'] ||
-                                                      
properties['oozie.https.keystore.pass']);
-        if (port === '11443' || isHttpsPropertiesEnabled) {
-          protocol = 'https';
-        }
-        return protocol;
-        break;
-      case "RANGER":
-        var rangerProperties = configProperties && 
configProperties.findProperty('type', 'ranger-admin-site');
-        var rangerSiteProperties = configProperties && 
configProperties.findProperty('type', 'ranger-site');
-        if (rangerProperties && rangerProperties.properties &&
-          
rangerProperties.properties['ranger.service.https.attrib.ssl.enabled'] == 
"true" &&
-          rangerProperties.properties['ranger.service.http.enabled'] == 
"false") {
-          //HDP2.3
-          return "https";
-        } else if (rangerProperties && rangerProperties.properties &&
-          
rangerProperties.properties['ranger.service.https.attrib.ssl.enabled'] == 
"false" &&
-          rangerProperties.properties['ranger.service.http.enabled'] == 
"true") {
-          //HDP2.3
-          return "http";
-        } else if (rangerSiteProperties && rangerSiteProperties.properties && 
rangerSiteProperties.properties['http.enabled'] == "false") {
-          //HDP2.2
-          return "https";
-        } else {
-          return "http";
+    }
+
+    var protocolType = Em.get(protocolConfig, 'type');
+
+    if ("HTTPS_ONLY" === protocolType)
+      return "https";
+    else if ("HTTP_ONLY" === protocolType)
+      return "http";
+    else {
+      var count = 0;
+      var checks = Em.get(protocolConfig, 'checks');
+      if(!checks){
+        if(hadoopSslEnabled)
+          return 'https';
+        else
+          return 'http';
+      }
+      checks.forEach(function(check){
+        var configType = Em.get(check, 'site');
+        var property = Em.get(check, 'property');
+        var desiredState = Em.get(check, 'desired');
+        var checkMeet = this.meetDesired(configProperties, configType, 
property, desiredState)
+        if(!checkMeet){
+          count++;
         }
-        break;
-      default:
-        return this.get('servicesSupportsHttps').contains(serviceName) && 
hadoopSslEnabled ? "https" : "http";
+      }, this);
+
+      if(count > 0)
+        return this.reverseType(protocolType);
+      else
+        return protocolType;
     }
   },
 
@@ -566,37 +665,28 @@ App.QuickViewLinks = Em.View.extend({
    * @returns {string}
    * @method setPort
    */
-  setPort: function (item, protocol, config) {
-    var configProperties = this.get('configProperties');
-    var configProp = config || item.get('http_config');
-    var defaultPort = item.get('default_http_port');
-    if (protocol === 'https' && (config || item.get('https_config'))) {
-      configProp = config || item.get('https_config');
-      if (item.get('default_https_port')) {
-        defaultPort = item.get('default_https_port');
-      }
-    }
-    var site = configProperties.findProperty('type', item.get('site'));
-    var propertyValue = site && site.properties && site.properties[configProp];
-    if (!propertyValue) {
-      if (item.get('serviceName') == 'RANGER') {
-        // HDP 2.3
-        var adminSite = configProperties.findProperty('type', 
'ranger-admin-site');
-        if (protocol === 'https') {
-          propertyValue = adminSite && adminSite.properties && 
adminSite.properties['ranger.service.https.port'];
-        } else {
-          propertyValue = adminSite && adminSite.properties && 
adminSite.properties['ranger.service.http.port'];
-        }
-      }
-    }
+  setPort: function (portConfigs, protocol, configProperties, 
configPropertyKey) {
 
-    if (!propertyValue) {
-      return defaultPort;
-    }
+    var defaultPort = Em.get(portConfigs, protocol+'_default_port');
+    var portProperty = Em.get(portConfigs,  protocol+'_property');
+    var site = configProperties.findProperty('type', Em.get(portConfigs, 
'site'));
+    var propertyValue = site && site.properties && 
site.properties[portProperty];
 
-    var re = new RegExp(item.get('regex'));
-    var portValue = propertyValue.match(re);
+    if (!propertyValue)
+      return defaultPort;
 
-    return portValue[1];
+    var regexValue = Em.get(portConfigs, 'regex');
+    regexValue = regexValue.trim();
+    if(regexValue){
+      var re = new RegExp(regexValue);
+      var portValue = propertyValue.match(re);
+      try {
+        return portValue[1];
+      }catch(err) {
+        return defaultPort;
+      }
+    } else {
+      return propertyValue;
+    }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/eca97913/ambari-web/test/views/common/quick_link_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/quick_link_view_test.js 
b/ambari-web/test/views/common/quick_link_view_test.js
index fc6b118..53c64ec 100644
--- a/ambari-web/test/views/common/quick_link_view_test.js
+++ b/ambari-web/test/views/common/quick_link_view_test.js
@@ -53,15 +53,15 @@ describe('App.QuickViewLinks', function () {
   describe("#didInsertElement()", function () {
     beforeEach(function () {
       sinon.stub(App.router, 'get').returns({p: 1});
-      sinon.stub(quickViewLinks, 'setQuickLinks');
+      sinon.stub(quickViewLinks, 'loadQuickLinksConfigurations');
     });
     afterEach(function () {
       App.router.get.restore();
-      quickViewLinks.setQuickLinks.restore();
+      quickViewLinks.loadQuickLinksConfigurations.restore();
     });
     it("", function () {
       quickViewLinks.didInsertElement();
-      expect(quickViewLinks.setQuickLinks.calledOnce).to.be.true;
+      
expect(quickViewLinks.loadQuickLinksConfigurations.calledOnce).to.be.true;
     });
   });
 
@@ -132,6 +132,7 @@ describe('App.QuickViewLinks', function () {
     afterEach(function () {
       quickViewLinks.setConfigProperties.restore();
       quickViewLinks.getQuickLinksHosts.restore();
+
     });
     it("", function () {
       var data = {
@@ -160,7 +161,7 @@ describe('App.QuickViewLinks', function () {
     afterEach(function () {
       quickViewLinks.getQuickLinksHosts.restore();
     });
-    it("call getQuickLinksHosts", function () {
+    it("call loadQuickLinksConfigurations", function () {
       quickViewLinks.loadTagsError();
       expect(quickViewLinks.getQuickLinksHosts.calledOnce).to.be.true;
     });
@@ -228,11 +229,10 @@ describe('App.QuickViewLinks', function () {
       quickViewLinks.setQuickLinksSuccessCallback();
       expect(quickViewLinks.setEmptyLinks.calledOnce).to.be.true;
     });
-    it("quickLinks is null", function () {
+    it("quickLinks is not configured", function () {
       this.mock.returns([{}]);
-      quickViewLinks.set('content.quickLinks', null);
       quickViewLinks.setQuickLinksSuccessCallback();
-      expect(quickViewLinks.setEmptyLinks.calledOnce).to.be.true;
+      expect(quickViewLinks.setEmptyLinks.calledOnce).to.be.false;
     });
     it("single host", function () {
       this.mock.returns([{hostName: 'host1'}]);
@@ -275,6 +275,7 @@ describe('App.QuickViewLinks', function () {
     });
     it("", function () {
       quickViewLinks.set('actualTags', [{siteName: 'hdfs-site'}]);
+      quickViewLinks.set('requiredSiteNames', ['hdfs-site']);
       quickViewLinks.setConfigProperties();
       expect(mock.getConfigsByTags.calledWith([{siteName: 
'hdfs-site'}])).to.be.true;
     });
@@ -463,73 +464,305 @@ describe('App.QuickViewLinks', function () {
 
   describe('#setProtocol', function () {
     var tests = [
+      //Yarn
       {
-        serviceName: "YARN", configProperties: [
-        {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTPS_ONLY'}}
-      ], m: "https for yarn", result: "https"
+        serviceName: "YARN",
+        configProperties: [
+          {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTPS_ONLY'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:[
+                     {property:"yarn.http.policy",
+                      desired:"HTTPS_ONLY",
+                      site:"yarn-site"}
+            ]
+          }
+        },
+        m: "https for yarn (checks for https passed)",
+        result: "https"
       },
       {
-        serviceName: "YARN", configProperties: [
-        {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTP_ONLY'}}
-      ], m: "http for yarn", result: "http"
+        serviceName: "YARN",
+        configProperties: [
+          {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTP_ONLY'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"http",
+            checks:[
+                     {property:"yarn.http.policy",
+                      desired:"HTTP_ONLY",
+                      site:"yarn-site"}
+            ]
+          }
+        },
+        m: "http for yarn (checks for http passed)",
+        result: "http"
       },
       {
-        serviceName: "YARN", configProperties: [
-        {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTP_ONLY'}}
-      ], m: "http for yarn (overrides hadoop.ssl.enabled)", result: "http"
+        serviceName: "YARN",
+        configProperties: [
+          {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTP_ONLY'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:[
+                     {property:"yarn.http.policy",
+                      desired:"HTTPS_ONLY",
+                      site:"yarn-site"}
+            ]
+          }
+        },
+        m: "http for yarn (checks for https did not pass)",
+        result: "http"
       },
       {
-        serviceName: "YARN", configProperties: [
-        {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTPS_ONLY'}}
-      ], m: "https for yarn (overrides hadoop.ssl.enabled)", result: "https"
+        serviceName: "YARN",
+        configProperties: [
+          {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTPS_ONLY'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"http",
+            checks:[
+                     {property:"yarn.http.policy",
+                      desired:"HTTP_ONLY",
+                      site:"yarn-site"}
+            ]
+          }
+        },
+        m: "https for yarn (checks for http did not pass)",
+        result: "https"
       },
       {
-        serviceName: "MAPREDUCE2", configProperties: [
-        {type: 'mapred-site', properties: {'mapreduce.jobhistory.http.policy': 
'HTTPS_ONLY'}}
-      ], m: "https for mapreduce2", result: "https"
+        serviceName: "YARN",
+        configProperties: [
+          {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTP_ONLY'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"HTTP_ONLY",
+            checks:[
+                     {property:"yarn.http.policy",
+                      desired:"HTTPS_ONLY",
+                      site:"yarn-site"}
+            ]
+          }
+        },
+        m: "http for yarn (override checks with specific protocol type)",
+        result: "http"
       },
       {
-        serviceName: "MAPREDUCE2", configProperties: [
-        {type: 'mapred-site', properties: {'mapreduce.jobhistory.http.policy': 
'HTTP_ONLY'}}
-      ], m: "http for mapreduce2", result: "http"
+        serviceName: "YARN",
+        configProperties: [
+          {type: 'yarn-site', properties: {'yarn.http.policy': 'HTTPS_ONLY'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"HTTPS_ONLY",
+            checks:[
+                     {property:"yarn.http.policy",
+                      desired:"HTTPS_ONLY",
+                      site:"yarn-site"}
+            ]
+          }
+        },
+        m: "https for yarn (override checks with specific protocol type)",
+        result: "https"
       },
+      //Any service - override hadoop.ssl.enabled
       {
-        serviceName: "ANYSERVICE", configProperties: [
-        {type: 'hdfs-site', properties: {'dfs.http.policy': 'HTTPS_ONLY'}}
-      ], m: "https for anyservice", servicesSupportsHttps: ["ANYSERVICE"], 
result: "https"
+        serviceName: "MyService",
+        configProperties: [
+          {type: 'myservice-site', properties: {'myservice.http.policy': 
'HTTPS_ONLY'}},
+          {type: 'hdfs-site', properties: {'dfs.http.policy':'HTTP_ONLY'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:[
+                     {property:"myservice.http.policy",
+                      desired:"HTTPS_ONLY",
+                      site:"myservice-site"}
+            ]
+          }
+        },
+        m: "https for MyService (checks for https passed, override 
hadoop.ssl.enabled)",
+        result: "https"
       },
+      //Oozie
       {
-        serviceName: "RANGER", configProperties: [
-        {type: 'ranger-site', properties: {'http.enabled': 'true'}}
-      ], m: "http for ranger (HDP2.2)", result: "http"
+        serviceName: "OOZIE",
+        configProperties: [
+          {type: 'oozie-site', properties: {'oozie.https.port': '12345', 
'oozie.https.keystore.file':'/tmp/oozie.jks', 
'oozie.https.keystore.pass':'mypass'}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:
+            [
+              {
+                "property":"oozie.https.port",
+                "desired":"EXIST",
+                "site":"oozie-site"
+              },
+              {
+                "property":"oozie.https.keystore.file",
+                "desired":"EXIST",
+                "site":"oozie-site"
+              },
+              {
+                "property":"oozie.https.keystore.pass",
+                "desired":"EXIST",
+                "site":"oozie-site"
+              }
+            ]
+          }
+        },
+        m: "https for oozie (checks for https passed)",
+        result: "https"
       },
       {
-        serviceName: "RANGER", configProperties: [
-        {type: 'ranger-site', properties: {'http.enabled': 'false'}}
-      ], m: "https for ranger (HDP2.2)", result: "https"
+        serviceName: "OOZIE",
+        configProperties: [
+          {type: 'oozie-site', properties: 
{"oozie.base.url":"http://c6401.ambari.apache.org:11000/oozie"}}
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:
+            [
+              {
+                "property":"oozie.https.port",
+                "desired":"EXIST",
+                "site":"oozie-site"
+              },
+              {
+                "property":"oozie.https.keystore.file",
+                "desired":"EXIST",
+                "site":"oozie-site"
+              },
+              {
+                "property":"oozie.https.keystore.pass",
+                "desired":"EXIST",
+                "site":"oozie-site"
+              }
+            ]
+          }
+        },
+        m: "http for oozie (checks for https did not pass)",
+        result: "http"
       },
+      //Ranger: HDP 2.2
       {
-        serviceName: "RANGER", configProperties: [
-        {
-          type: 'ranger-admin-site',
-          properties: {'ranger.service.http.enabled': 'true', 
'ranger.service.https.attrib.ssl.enabled': 'false'}
-        }
-      ], m: "http for ranger (HDP2.3)", result: "http"
+        serviceName: "RANGER",
+        configProperties: [{type: 'ranger-site', properties: {'http.enabled': 
'false'}}],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:
+            [
+              {
+                "property":"http.enabled",
+                "desired":"false",
+                "site":"ranger-site"
+              }
+            ]
+          }
+        },
+        m: "https for ranger (HDP2.2, checks passed)",
+        result: "https"
       },
       {
-        serviceName: "RANGER", configProperties: [
-        {
-          type: 'ranger-admin-site',
-          properties: {'ranger.service.http.enabled': 'false', 
'ranger.service.https.attrib.ssl.enabled': 'true'}
-        }
-      ], m: "https for ranger (HDP2.3)", result: "https"
+        serviceName: "RANGER",
+        configProperties: [{type: 'ranger-site', properties: {'http.enabled': 
'true'}}],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:
+            [
+              {
+                "property":"http.enabled",
+                "desired":"false",
+                "site":"ranger-site"
+              }
+            ]
+          }
+        },
+        m: "http for ranger (HDP2.2, checks for https did not pass)",
+        result: "http"
+      },
+      //Ranger: HDP 2.3
+      {
+        serviceName: "RANGER",
+        configProperties:
+        [
+          {
+            type: 'ranger-admin-site',
+            properties: {'ranger.service.http.enabled': 'false', 
'ranger.service.https.attrib.ssl.enabled': 'true'}
+          },
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:
+            [
+              {
+                "property":"ranger.service.http.enabled",
+                "desired":"false",
+                "site":"ranger-admin-site"
+              },
+              {
+                "property":"ranger.service.https.attrib.ssl.enabled",
+                "desired":"true",
+                "site":"ranger-admin-site"
+              }
+            ]
+          }
+        },
+
+        m: "https for ranger (HDP2.3, checks passed)",
+        result: "https"
+      },
+      {
+        serviceName: "RANGER",
+        configProperties:
+        [
+          {
+            type: 'ranger-admin-site',
+            properties: {'ranger.service.http.enabled': 'true', 
'ranger.service.https.attrib.ssl.enabled': 'false'}
+          },
+        ],
+        quickLinksConfig: {
+          protocol:{
+            type:"https",
+            checks:
+            [
+              {
+                "property":"ranger.service.http.enabled",
+                "desired":"false",
+                "site":"ranger-admin-site"
+              },
+              {
+                "property":"ranger.service.https.attrib.ssl.enabled",
+                "desired":"true",
+                "site":"ranger-admin-site"
+              }
+            ]
+          }
+        },
+        m: "http for ranger (HDP2.3, checks for https did not pass)",
+        result: "http"
       }
     ];
 
     tests.forEach(function (t) {
       it(t.m, function () {
         quickViewLinks.set('servicesSupportsHttps', t.servicesSupportsHttps);
-        expect(quickViewLinks.setProtocol(t.serviceName, t.configProperties, 
t.ambariProperties)).to.equal(t.result);
+        expect(quickViewLinks.setProtocol(t.configProperties, 
t.quickLinksConfig)).to.equal(t.result);
       });
     });
   });
@@ -537,86 +770,43 @@ describe('App.QuickViewLinks', function () {
   describe('#setPort', function () {
     var testData = [
       Em.Object.create({
-        'service_id': 'YARN',
         'protocol': 'http',
-        'result': '8088',
-        'default_http_port': '8088',
-        'default_https_port': '8090',
-        'regex': '\\w*:(\\d+)'
-      }),
-      Em.Object.create({
-        'service_id': 'YARN',
-        'protocol': 'https',
-        'https_config': 'https_config',
-        'result': '8090',
-        'default_http_port': '8088',
-        'default_https_port': '8090',
-        'regex': '\\w*:(\\d+)'
+        'port':{
+          'http_property':'yarn.timeline-service.webapp.address',
+          'http_default_port':'8188',
+          'https_property':'yarn.timeline-service.webapp.https.address',
+          'https_default_port':'8090',
+          'regex': '\\w*:(\\d+)',
+          'site':'yarn-site'
+        },
+        'configProperties':
+        [
+          {
+            'type': 'yarn-site',
+            'properties': {'yarn.timeline-service.webapp.address': 
'c6401.ambari.apache.org:8188'}
+          },
+        ],
+        'result': '8188',
       }),
+
       Em.Object.create({
-        'service_id': 'YARN',
         'protocol': 'https',
-        'https_config': 'https_config',
+        'port':{
+          'http_property':'yarn.timeline-service.webapp.address',
+          'http_default_port':'8188',
+          'https_property':'yarn.timeline-service.webapp.https.address',
+          'https_default_port':'8090',
+          'regex': '\\w*:(\\d+)',
+          'site':'yarn-site'
+        },
+        'configProperties':
+        [
+          {
+            'type': 'yarn-site',
+            'properties': {'yarn.timeline-service.webapp.https.address': 
'c6401.ambari.apache.org:8090'}
+          },
+        ],
         'result': '8090',
-        'default_http_port': '8088',
-        'default_https_port': '8090',
-        'regex': '\\w*:(\\d+)'
-      }),
-      Em.Object.create({
-        'service_id': 'YARN',
-        'protocol': 'https',
-        'https_config': 'https_config',
-        'config': 'https_config_custom',
-        'site': 'yarn-site',
-        'result': '9091',
-        'default_http_port': '8088',
-        'default_https_port': '8090',
-        'regex': '\\w*:(\\d+)',
-        'configProperties': [{
-          'type': 'yarn-site',
-          'properties': {
-            'https_config': 'h:9090',
-            'https_config_custom': 'h:9091'
-          }
-        }]
-      }),
-      Em.Object.create({
-        'service_id': 'YARN',
-        'protocol': 'https',
-        'http_config': 'http_config',
-        'https_config': 'https_config',
-        'site': 'yarn-site',
-        'result': '9090',
-        'default_http_port': '8088',
-        'default_https_port': '8090',
-        'regex': '\\w*:(\\d+)',
-        'configProperties': [{
-          'type': 'yarn-site',
-          'properties': {
-            'http_config': 'h:9088',
-            'https_config': 'h:9090'
-          }
-        }]
-      }),
-      Em.Object.create({
-        'service_id': 'RANGER',
-        'protocol': 'http',
-        'http_config': 'http_config',
-        'https_config': 'https_config',
-        'result': '6080',
-        'default_http_port': '6080',
-        'default_https_port': '6182',
-        'regex': '(\\d*)+'
-      }),
-      Em.Object.create({
-        'service_id': 'RANGER',
-        'protocol': 'https',
-        'http_config': 'http_config',
-        'https_config': 'https_config',
-        'result': '6182',
-        'default_http_port': '6080',
-        'default_https_port': '6182',
-        'regex': '(\\d*)+'
       })
     ];
 
@@ -627,7 +817,7 @@ describe('App.QuickViewLinks', function () {
     testData.forEach(function (item) {
       it(item.service_id + ' ' + item.protocol, function () {
         quickViewLinks.set('configProperties', item.configProperties || []);
-        expect(quickViewLinks.setPort(item, item.protocol, 
item.config)).to.equal(item.result);
+        expect(quickViewLinks.setPort(item.port, item.protocol, 
item.configProperties)).to.equal(item.result);
       })
     }, this);
   });

Reply via email to