You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/10/16 17:06:13 UTC

[19/23] knox git commit: Merge branch 'master' into KNOX-998-Package_Restructuring

Merge branch 'master' into KNOX-998-Package_Restructuring

# Conflicts:
#	gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java
#	gateway-discovery-ambari/src/main/resources/ambari-service-discovery-component-config-mapping.properties
#	gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/PicketlinkMessages.java
#	gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/deploy/PicketlinkConf.java
#	gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/deploy/PicketlinkFederationProviderContributor.java
#	gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/filter/CaptureOriginalURLFilter.java
#	gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/filter/PicketlinkIdentityAdapter.java
#	gateway-provider-security-picketlink/src/test/java/org/apache/knox/gateway/picketlink/PicketlinkTest.java
#	gateway-server/src/main/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorHandler.java
#	gateway-server/src/test/java/org/apache/knox/gateway/topology/simple/SimpleDescriptorHandlerTest.java
#	gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java


Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/8affbc02
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/8affbc02
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/8affbc02

Branch: refs/heads/KNOX-998-Package_Restructuring
Commit: 8affbc0226fb2e587bdadaac9270b071d52b8062
Parents: 557d569 92b1505
Author: Sandeep More <mo...@apache.org>
Authored: Mon Oct 16 10:06:25 2017 -0400
Committer: Sandeep More <mo...@apache.org>
Committed: Mon Oct 16 10:06:25 2017 -0400

----------------------------------------------------------------------
 .../ambari/AmbariDynamicServiceURLCreator.java  | 151 ++++
 .../ambari/ConditionalValueHandler.java         |  24 +
 .../discovery/ambari/PropertyEqualsHandler.java |  76 ++
 .../ambari/ServiceURLPropertyConfig.java        | 324 +++++++
 .../discovery/ambari/SimpleValueHandler.java    |  32 +
 .../discovery/ambari/AmbariCluster.java         |   7 +-
 .../discovery/ambari/AmbariComponent.java       |  27 +-
 .../ambari/AmbariServiceDiscovery.java          |  58 +-
 .../ambari/AmbariServiceDiscoveryMessages.java  |  64 +-
 .../ambari/AmbariServiceURLCreator.java         | 184 ----
 ...iscovery-component-config-mapping.properties |  36 +
 .../ambari-service-discovery-url-mappings.xml   | 398 +++++++++
 .../AmbariDynamicServiceURLCreatorTest.java     | 876 +++++++++++++++++++
 .../ambari/AmbariServiceDiscoveryTest.java      |   4 +-
 .../jwt/filter/AbstractJWTFilter.java           |   2 +-
 .../federation/AbstractJWTFilterTest.java       |  31 +
 gateway-provider-security-picketlink/pom.xml    |  76 --
 .../gateway/picketlink/PicketlinkMessages.java  |  40 -
 .../picketlink/deploy/PicketlinkConf.java       | 194 ----
 ...PicketlinkFederationProviderContributor.java | 132 ---
 .../filter/CaptureOriginalURLFilter.java        |  89 --
 .../filter/PicketlinkIdentityAdapter.java       | 102 ---
 .../knox/gateway/picketlink/PicketlinkTest.java |  29 -
 gateway-release/pom.xml                         |   4 -
 .../gateway/websockets/ProxyInboundClient.java  | 107 +++
 .../impl/DefaultServiceRegistryService.java     |  50 +-
 .../security/impl/DefaultAliasService.java      |  12 +-
 .../simple/SimpleDescriptorHandler.java         |  69 +-
 .../simple/SimpleDescriptorMessages.java        |   8 +-
 .../websockets/GatewayWebsocketHandler.java     |  41 +-
 .../websockets/ProxyWebSocketAdapter.java       |  19 +-
 .../websockets/ProxyInboundClientTest.java      | 374 ++++++++
 .../simple/SimpleDescriptorHandlerTest.java     | 181 +++-
 .../services/ambariui/2.2.0/service.xml         |   5 +
 .../resources/services/atlas/0.8.0/rewrite.xml  |   6 +-
 .../gateway/service/knoxsso/WebSSOResource.java |   2 +-
 .../service/knoxsso/WebSSOResourceTest.java     |  58 ++
 .../service/knoxtoken/TokenResource.java        |  37 +-
 .../knoxtoken/TokenServiceResourceTest.java     | 203 +++++
 gateway-shell-release/pom.xml                   |   4 +
 .../knox/gateway/util/urltemplate/Parser.java   |  10 +-
 .../gateway/util/urltemplate/ParserTest.java    |  17 +
 pom.xml                                         |  44 +-
 43 files changed, 3217 insertions(+), 990 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/8affbc02/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariCluster.java
----------------------------------------------------------------------
diff --cc gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariCluster.java
index fa9d710,0000000..d65bff7
mode 100644,000000..100644
--- a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariCluster.java
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariCluster.java
@@@ -1,114 -1,0 +1,115 @@@
 +/**
 + * 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.ambari;
 +
 +import org.apache.knox.gateway.topology.discovery.ServiceDiscovery;
 +
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.List;
 +import java.util.Map;
 +
 +class AmbariCluster implements ServiceDiscovery.Cluster {
 +
 +    private String name = null;
 +
-     private AmbariServiceURLCreator urlCreator = new AmbariServiceURLCreator();
++    private AmbariDynamicServiceURLCreator urlCreator;
 +
 +    private Map<String, Map<String, ServiceConfiguration>> serviceConfigurations = new HashMap<>();
 +
 +    private Map<String, AmbariComponent> components = null;
 +
 +
 +    AmbariCluster(String name) {
 +        this.name = name;
-         components = new HashMap<String, AmbariComponent>();
++        components = new HashMap<>();
++        urlCreator = new AmbariDynamicServiceURLCreator(this);
 +    }
 +
 +    void addServiceConfiguration(String serviceName, String configurationType, ServiceConfiguration serviceConfig) {
 +        if (!serviceConfigurations.keySet().contains(serviceName)) {
 +            serviceConfigurations.put(serviceName, new HashMap<String, ServiceConfiguration>());
 +        }
 +        serviceConfigurations.get(serviceName).put(configurationType, serviceConfig);
 +    }
 +
 +
 +    void addComponent(AmbariComponent component) {
 +        components.put(component.getName(), component);
 +    }
 +
 +
 +    ServiceConfiguration getServiceConfiguration(String serviceName, String configurationType) {
 +        ServiceConfiguration sc = null;
 +        Map<String, ServiceConfiguration> configs = serviceConfigurations.get(serviceName);
 +        if (configs != null) {
 +            sc = configs.get(configurationType);
 +        }
 +        return sc;
 +    }
 +
 +
 +    Map<String, AmbariComponent> getComponents() {
 +        return components;
 +    }
 +
 +
 +    AmbariComponent getComponent(String name) {
 +        return components.get(name);
 +    }
 +
 +
 +    @Override
 +    public String getName() {
 +        return name;
 +    }
 +
 +
 +    @Override
 +    public List<String> getServiceURLs(String serviceName) {
 +        List<String> urls = new ArrayList<>();
-         urls.addAll(urlCreator.create(this, serviceName));
++        urls.addAll(urlCreator.create(serviceName));
 +        return urls;
 +    }
 +
 +
 +    static class ServiceConfiguration {
 +
 +        private String type;
 +        private String version;
 +        private Map<String, String> props;
 +
 +        ServiceConfiguration(String type, String version, Map<String, String> properties) {
 +            this.type = type;
 +            this.version = version;
 +            this.props = properties;
 +        }
 +
 +        public String getVersion() {
 +            return version;
 +        }
 +
 +        public String getType() {
 +            return type;
 +        }
 +
 +        public Map<String, String> getProperties() {
 +            return props;
 +        }
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/8affbc02/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariComponent.java
----------------------------------------------------------------------
diff --cc gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariComponent.java
index 4750e7e,0000000..c8e7c6d
mode 100644,000000..100644
--- a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariComponent.java
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariComponent.java
@@@ -1,76 -1,0 +1,85 @@@
 +/**
 + * 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.ambari;
 +
++import java.util.ArrayList;
 +import java.util.List;
 +import java.util.Map;
 +
 +class AmbariComponent {
 +
 +    private String clusterName = null;
 +    private String serviceName = null;
 +    private String name        = null;
 +    private String version     = null;
 +
-     private List<String> hostNames = null;
++    private List<String> hostNames = new ArrayList<>();
 +
 +    private Map<String, String> properties = null;
 +
 +    AmbariComponent(String              name,
 +                    String              version,
 +                    String              cluster,
 +                    String              service,
 +                    List<String>        hostNames,
 +                    Map<String, String> properties) {
 +        this.name = name;
 +        this.serviceName = service;
 +        this.clusterName = cluster;
 +        this.version = version;
-         this.hostNames = hostNames;
 +        this.properties = properties;
++
++        if (hostNames != null) {
++            // Add the hostnames individually to prevent adding any null values
++            for (String hostName : hostNames) {
++                if (hostName != null) {
++                    this.hostNames.add(hostName);
++                }
++            }
++        }
 +    }
 +
-     public String getVersion() {
++    String getVersion() {
 +        return version;
 +    }
 +
-     public String getName() {
++    String getName() {
 +        return name;
 +    }
 +
-     public String getServiceName() {
++    String getServiceName() {
 +        return serviceName;
 +    }
 +
-     public String getClusterName() {
++    String getClusterName() {
 +        return clusterName;
 +    }
 +
-     public List<String> getHostNames() {
++    List<String> getHostNames() {
 +        return hostNames;
 +    }
 +
-     public Map<String, String> getConfigProperties() {
++    Map<String, String> getConfigProperties() {
 +        return properties;
 +    }
 +
-     public String getConfigProperty(String propertyName) {
++    String getConfigProperty(String propertyName) {
 +        return properties.get(propertyName);
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/8affbc02/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
----------------------------------------------------------------------
diff --cc gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
index da03564,0000000..70af903
mode 100644,000000..100644
--- a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
@@@ -1,291 -1,0 +1,305 @@@
 +/**
 + * 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.ambari;
 +
++import java.io.IOException;
++import java.util.ArrayList;
++import java.util.HashMap;
++import java.util.List;
++import java.util.Map;
++import java.util.Properties;
++
 +import net.minidev.json.JSONArray;
 +import net.minidev.json.JSONObject;
 +import net.minidev.json.JSONValue;
 +import org.apache.knox.gateway.config.ConfigurationException;
 +import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 +import org.apache.knox.gateway.services.security.AliasService;
 +import org.apache.knox.gateway.services.security.AliasServiceException;
 +import org.apache.knox.gateway.topology.discovery.GatewayService;
 +import org.apache.knox.gateway.topology.discovery.ServiceDiscovery;
 +import org.apache.knox.gateway.topology.discovery.ServiceDiscoveryConfig;
 +import org.apache.http.HttpEntity;
 +import org.apache.http.HttpStatus;
 +import org.apache.http.client.methods.CloseableHttpResponse;
 +import org.apache.http.client.methods.HttpGet;
 +import org.apache.http.impl.client.CloseableHttpClient;
 +import org.apache.http.message.BasicHeader;
 +import org.apache.http.util.EntityUtils;
 +
- import java.io.IOException;
- import java.util.*;
- 
 +
 +class AmbariServiceDiscovery implements ServiceDiscovery {
 +
 +    static final String TYPE = "AMBARI";
 +
 +    static final String AMBARI_CLUSTERS_URI = "/api/v1/clusters";
 +
 +    static final String AMBARI_HOSTROLES_URI =
 +                                       AMBARI_CLUSTERS_URI + "/%s/services?fields=components/host_components/HostRoles";
 +
 +    static final String AMBARI_SERVICECONFIGS_URI =
 +            AMBARI_CLUSTERS_URI + "/%s/configurations/service_config_versions?is_current=true";
 +
++    private static final String COMPONENT_CONFIG_MAPPING_FILE =
++                                                        "ambari-service-discovery-component-config-mapping.properties";
++
++    private static final AmbariServiceDiscoveryMessages log = MessagesFactory.get(AmbariServiceDiscoveryMessages.class);
++
 +    // Map of component names to service configuration types
 +    private static Map<String, String> componentServiceConfigs = new HashMap<>();
 +    static {
-         componentServiceConfigs.put("NAMENODE", "hdfs-site");
-         componentServiceConfigs.put("RESOURCEMANAGER", "yarn-site");
-         componentServiceConfigs.put("OOZIE_SERVER", "oozie-site");
-         componentServiceConfigs.put("HIVE_SERVER", "hive-site");
-         componentServiceConfigs.put("WEBHCAT_SERVER", "webhcat-site");
-         componentServiceConfigs.put("HBASE_MASTER", "hbase-site");
-     } // TODO: Are there other service components, for which the endpoints can be discovered via Ambari?
++        try {
++            Properties configMapping = new Properties();
++            configMapping.load(AmbariServiceDiscovery.class.getClassLoader().getResourceAsStream(COMPONENT_CONFIG_MAPPING_FILE));
++            for (String componentName : configMapping.stringPropertyNames()) {
++                componentServiceConfigs.put(componentName, configMapping.getProperty(componentName));
++            }
++        } catch (Exception e) {
++            log.failedToLoadServiceDiscoveryConfiguration(COMPONENT_CONFIG_MAPPING_FILE, e);
++        }
++    }
 +
 +    private static final String DEFAULT_USER_ALIAS = "ambari.discovery.user";
 +    private static final String DEFAULT_PWD_ALIAS  = "ambari.discovery.password";
 +
-     private static AmbariServiceURLCreator urlCreator = new AmbariServiceURLCreator();
- 
-     private AmbariServiceDiscoveryMessages log = MessagesFactory.get(AmbariServiceDiscoveryMessages.class);
- 
 +    @GatewayService
 +    private AliasService aliasService;
 +
 +    private CloseableHttpClient httpClient = null;
 +
-     private Map<String, Map<String, String>> serviceConfiguration = new HashMap<>();
- 
 +
 +    AmbariServiceDiscovery() {
 +        httpClient = org.apache.http.impl.client.HttpClients.createDefault();
 +    }
 +
 +
 +    @Override
 +    public String getType() {
 +        return TYPE;
 +    }
 +
 +
 +    @Override
 +    public Map<String, Cluster> discover(ServiceDiscoveryConfig config) {
 +        Map<String, Cluster> clusters = new HashMap<String, Cluster>();
 +
 +        String discoveryAddress = config.getAddress();
 +
 +        // Invoke Ambari REST API to discover the available clusters
 +        String clustersDiscoveryURL = String.format("%s" + AMBARI_CLUSTERS_URI, discoveryAddress);
 +
 +        JSONObject json = invokeREST(clustersDiscoveryURL, config.getUser(), config.getPasswordAlias());
 +
 +        // Parse the cluster names from the response, and perform the cluster discovery
 +        JSONArray clusterItems = (JSONArray) json.get("items");
 +        for (Object clusterItem : clusterItems) {
 +            String clusterName = (String) ((JSONObject)((JSONObject) clusterItem).get("Clusters")).get("cluster_name");
 +            try {
 +                Cluster c = discover(config, clusterName);
 +                clusters.put(clusterName, c);
 +            } catch (Exception e) {
 +                log.clusterDiscoveryError(clusterName, e);
 +            }
 +        }
 +
 +        return clusters;
 +    }
 +
 +
 +    @Override
 +    public Cluster discover(ServiceDiscoveryConfig config, String clusterName) {
 +        AmbariCluster cluster = new AmbariCluster(clusterName);
 +
 +        Map<String, String> serviceComponents = new HashMap<>();
 +
 +        String discoveryAddress = config.getAddress();
 +        String discoveryUser = config.getUser();
 +        String discoveryPwdAlias = config.getPasswordAlias();
 +
 +        Map<String, List<String>> componentHostNames = new HashMap<>();
 +        String hostRolesURL = String.format("%s" + AMBARI_HOSTROLES_URI, discoveryAddress, clusterName);
 +        JSONObject hostRolesJSON = invokeREST(hostRolesURL, discoveryUser, discoveryPwdAlias);
 +        if (hostRolesJSON != null) {
 +            // Process the host roles JSON
 +            JSONArray items = (JSONArray) hostRolesJSON.get("items");
 +            for (Object obj : items) {
 +                JSONArray components = (JSONArray) ((JSONObject) obj).get("components");
 +                for (Object component : components) {
 +                    JSONArray hostComponents = (JSONArray) ((JSONObject) component).get("host_components");
 +                    for (Object hostComponent : hostComponents) {
 +                        JSONObject hostRoles = (JSONObject) ((JSONObject) hostComponent).get("HostRoles");
 +                        String serviceName = (String) hostRoles.get("service_name");
 +                        String componentName = (String) hostRoles.get("component_name");
 +
 +                        serviceComponents.put(componentName, serviceName);
 +
- //                    String hostName = (String) hostRoles.get("host_name");
-                         String hostName = (String) hostRoles.get("public_host_name"); // Assuming public host name is most applicable
-                         log.discoveredServiceHost(serviceName, hostName);
-                         if (!componentHostNames.containsKey(componentName)) {
-                             componentHostNames.put(componentName, new ArrayList<String>());
++                        // Assuming public host name is more applicable than host_name
++                        String hostName = (String) hostRoles.get("public_host_name");
++                        if (hostName == null) {
++                            // Some (even slightly) older versions of Ambari/HDP do not return public_host_name,
++                            // so fall back to host_name in those cases.
++                            hostName = (String) hostRoles.get("host_name");
++                        }
++
++                        if (hostName != null) {
++                            log.discoveredServiceHost(serviceName, hostName);
++                            if (!componentHostNames.containsKey(componentName)) {
++                                componentHostNames.put(componentName, new ArrayList<String>());
++                            }
++                            componentHostNames.get(componentName).add(hostName);
 +                        }
-                         componentHostNames.get(componentName).add(hostName);
 +                    }
 +                }
 +            }
 +        }
 +
 +        Map<String, Map<String, AmbariCluster.ServiceConfiguration>> serviceConfigurations =
 +                                                 new HashMap<String, Map<String, AmbariCluster.ServiceConfiguration>>();
 +        String serviceConfigsURL = String.format("%s" + AMBARI_SERVICECONFIGS_URI, discoveryAddress, clusterName);
 +        JSONObject serviceConfigsJSON = invokeREST(serviceConfigsURL, discoveryUser, discoveryPwdAlias);
 +        if (serviceConfigsJSON != null) {
 +            // Process the service configurations
 +            JSONArray serviceConfigs = (JSONArray) serviceConfigsJSON.get("items");
 +            for (Object serviceConfig : serviceConfigs) {
 +                String serviceName = (String) ((JSONObject) serviceConfig).get("service_name");
 +                JSONArray configurations = (JSONArray) ((JSONObject) serviceConfig).get("configurations");
 +                for (Object configuration : configurations) {
 +                    String configType = (String) ((JSONObject) configuration).get("type");
 +                    String configVersion = String.valueOf(((JSONObject) configuration).get("version"));
 +
 +                    Map<String, String> configProps = new HashMap<String, String>();
 +                    JSONObject configProperties = (JSONObject) ((JSONObject) configuration).get("properties");
 +                    for (String propertyName : configProperties.keySet()) {
 +                        configProps.put(propertyName, String.valueOf(((JSONObject) configProperties).get(propertyName)));
 +                    }
 +                    if (!serviceConfigurations.containsKey(serviceName)) {
 +                        serviceConfigurations.put(serviceName, new HashMap<String, AmbariCluster.ServiceConfiguration>());
 +                    }
 +                    serviceConfigurations.get(serviceName).put(configType, new AmbariCluster.ServiceConfiguration(configType, configVersion, configProps));
 +                    cluster.addServiceConfiguration(serviceName, configType, new AmbariCluster.ServiceConfiguration(configType, configVersion, configProps));
 +                }
 +            }
 +        }
 +
 +        // Construct the AmbariCluster model
 +        for (String componentName : serviceComponents.keySet()) {
 +            String serviceName = serviceComponents.get(componentName);
 +            List<String> hostNames = componentHostNames.get(componentName);
 +
 +            Map<String, AmbariCluster.ServiceConfiguration> configs = serviceConfigurations.get(serviceName);
 +            String configType = componentServiceConfigs.get(componentName);
 +            if (configType != null) {
 +                AmbariCluster.ServiceConfiguration svcConfig = configs.get(configType);
 +                AmbariComponent c = new AmbariComponent(componentName,
 +                                                        svcConfig.getVersion(),
 +                                                        clusterName,
 +                                                        serviceName,
 +                                                        hostNames,
 +                                                        svcConfig.getProperties());
 +                cluster.addComponent(c);
 +            }
 +        }
 +
 +        return cluster;
 +    }
 +
 +
 +    protected JSONObject invokeREST(String url, String username, String passwordAlias) {
 +        JSONObject result = null;
 +
 +        CloseableHttpResponse response = null;
 +        try {
 +            HttpGet request = new HttpGet(url);
 +
 +            // If no configured username, then use default username alias
 +            String password = null;
 +            if (username == null) {
 +                if (aliasService != null) {
 +                    try {
 +                        char[] defaultUser = aliasService.getPasswordFromAliasForGateway(DEFAULT_USER_ALIAS);
 +                        if (defaultUser != null) {
 +                            username = new String(defaultUser);
 +                        }
 +                    } catch (AliasServiceException e) {
 +                        log.aliasServiceUserError(DEFAULT_USER_ALIAS, e.getLocalizedMessage());
 +                    }
 +                }
 +
 +                // If username is still null
 +                if (username == null) {
 +                    log.aliasServiceUserNotFound();
 +                    throw new ConfigurationException("No username is configured for Ambari service discovery.");
 +                }
 +            }
 +
 +            if (aliasService != null) {
 +                // If not password alias is configured, then try the default alias
 +                if (passwordAlias == null) {
 +                    passwordAlias = DEFAULT_PWD_ALIAS;
 +                }
 +                try {
 +                    char[] pwd = aliasService.getPasswordFromAliasForGateway(passwordAlias);
 +                    if (pwd != null) {
 +                        password = new String(pwd);
 +                    }
 +
 +                } catch (AliasServiceException e) {
 +                    log.aliasServicePasswordError(passwordAlias, e.getLocalizedMessage());
 +                }
 +            }
 +
 +            // If the password could not be determined
 +            if (password == null) {
 +                log.aliasServicePasswordNotFound();
 +                throw new ConfigurationException("No password is configured for Ambari service discovery.");
 +            }
 +
 +            // Add an auth header if credentials are available
 +            String encodedCreds =
 +                    org.apache.commons.codec.binary.Base64.encodeBase64String((username + ":" + password).getBytes());
 +            request.addHeader(new BasicHeader("Authorization", "Basic " + encodedCreds));
 +
 +            response = httpClient.execute(request);
 +
 +            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
 +                HttpEntity entity = response.getEntity();
 +                if (entity != null) {
 +                    result = (JSONObject) JSONValue.parse((EntityUtils.toString(entity)));
 +                    log.debugJSON(result.toJSONString());
 +                } else {
 +                    log.noJSON(url);
 +                }
 +            } else {
 +                log.unexpectedRestResponseStatusCode(url, response.getStatusLine().getStatusCode());
 +            }
 +
 +        } catch (IOException e) {
 +            log.restInvocationError(url, e);
 +        } finally {
 +            if(response != null) {
 +                try {
 +                    response.close();
 +                } catch (IOException e) {
 +                    // Ignore
 +                }
 +            }
 +        }
 +        return result;
 +    }
 +
 +
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/8affbc02/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryMessages.java
----------------------------------------------------------------------
diff --cc gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryMessages.java
index 2a153bb,0000000..d91edef
mode 100644,000000..100644
--- a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryMessages.java
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryMessages.java
@@@ -1,81 -1,0 +1,121 @@@
 +/**
 + * 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.ambari;
 +
 +import org.apache.knox.gateway.i18n.messages.Message;
 +import org.apache.knox.gateway.i18n.messages.MessageLevel;
 +import org.apache.knox.gateway.i18n.messages.Messages;
 +import org.apache.knox.gateway.i18n.messages.StackTrace;
 +
- @Messages(logger="org.apache.gateway.topology.discovery.ambari")
++@Messages(logger="org.apache.hadoop.gateway.topology.discovery.ambari")
 +public interface AmbariServiceDiscoveryMessages {
 +
 +    @Message(level = MessageLevel.ERROR,
-             text = "Encountered an error during cluster {0} discovery: {1}")
++            text = "Failed to load service discovery configuration: {1}")
++    void failedToLoadServiceDiscoveryConfiguration(@StackTrace(level = MessageLevel.ERROR) Exception e);
++
++    @Message(level = MessageLevel.ERROR,
++             text = "Failed to load service discovery configuration {0}: {1}")
++    void failedToLoadServiceDiscoveryConfiguration(final String configuration,
++                               @StackTrace(level = MessageLevel.ERROR) Exception e);
++
++    @Message(level = MessageLevel.ERROR,
++             text = "Encountered an error during cluster {0} discovery: {1}")
 +    void clusterDiscoveryError(final String clusterName,
 +                               @StackTrace(level = MessageLevel.ERROR) Exception e);
 +
 +
 +    @Message(level = MessageLevel.DEBUG,
-             text = "REST invocation {0} failed: {1}")
++             text = "REST invocation {0} failed: {1}")
 +    void restInvocationError(final String url,
 +                             @StackTrace(level = MessageLevel.ERROR) Exception e);
 +
 +
 +    @Message(level = MessageLevel.ERROR,
-             text = "Encountered an error attempting to determine the user for alias {0} : {1}")
++             text = "Encountered an error attempting to determine the user for alias {0} : {1}")
 +    void aliasServiceUserError(final String alias, final String error);
 +
 +
 +    @Message(level = MessageLevel.ERROR,
-             text = "Encountered an error attempting to determine the password for alias {0} : {1}")
++             text = "Encountered an error attempting to determine the password for alias {0} : {1}")
 +    void aliasServicePasswordError(final String alias, final String error);
 +
 +
 +    @Message(level = MessageLevel.ERROR,
-             text = "No user configured for Ambari service discovery.")
++             text = "No user configured for Ambari service discovery.")
 +    void aliasServiceUserNotFound();
 +
 +
 +    @Message(level = MessageLevel.ERROR,
-             text = "No password configured for Ambari service discovery.")
++             text = "No password configured for Ambari service discovery.")
 +    void aliasServicePasswordNotFound();
 +
 +
 +    @Message(level = MessageLevel.ERROR,
-             text = "Unexpected REST invocation response code for {0} : {1}")
++             text = "Unexpected REST invocation response code for {0} : {1}")
 +    void unexpectedRestResponseStatusCode(final String url, int responseStatusCode);
 +
 +
 +    @Message(level = MessageLevel.ERROR,
-             text = "REST invocation {0} yielded a response without any JSON.")
++             text = "REST invocation {0} yielded a response without any JSON.")
 +    void noJSON(final String url);
 +
 +
 +    @Message(level = MessageLevel.DEBUG,
-             text = "REST invocation result: {0}")
++             text = "REST invocation result: {0}")
 +    void debugJSON(final String json);
 +
++    @Message(level = MessageLevel.DEBUG,
++            text = "Loaded component configuration mappings: {0}")
++    void loadedComponentConfigMappings(final String mappings);
 +
-     @Message(level = MessageLevel.INFO,
-             text = "Discovered: Service: {0}, Host: {1}")
++    @Message(level = MessageLevel.ERROR,
++             text = "Failed to load component configuration property mappings {0}: {1}")
++    void failedToLoadComponentConfigMappings(final String mappings,
++                                             @StackTrace(level = MessageLevel.ERROR) Exception e);
++
++    @Message(level = MessageLevel.DEBUG,
++             text = "Discovered: Service: {0}, Host: {1}")
 +    void discoveredServiceHost(final String serviceName, final String hostName);
 +
 +
++    @Message(level = MessageLevel.DEBUG,
++             text = "Querying the cluster for the {0} configuration ({1}) property: {2}")
++    void lookingUpServiceConfigProperty(final String serviceName, final String configType, final String propertyName);
++
++
++    @Message(level = MessageLevel.DEBUG,
++             text = "Querying the cluster for the {0} component configuration property: {1}")
++    void lookingUpComponentConfigProperty(final String componentName, final String propertyName);
++
++
++    @Message(level = MessageLevel.DEBUG,
++             text = "Querying the cluster for the {0} component's hosts")
++    void lookingUpComponentHosts(final String componentName);
++
++
++    @Message(level = MessageLevel.DEBUG,
++            text = "Handling a derived service URL mapping property for the {0} service: type = {1}, name = {2}")
++    void handlingDerivedProperty(final String serviceName, final String propertyType, final String propertyName);
++
++
++    @Message(level = MessageLevel.DEBUG,
++            text = "Determined the service URL mapping property {0} value: {1}")
++    void determinedPropertyValue(final String propertyName, final String propertyValue);
 +
 +
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/8affbc02/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java
----------------------------------------------------------------------
diff --cc gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java
index 302eda7,0000000..e69de29
mode 100644,000000..100644
--- a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java

http://git-wip-us.apache.org/repos/asf/knox/blob/8affbc02/gateway-discovery-ambari/src/test/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryTest.java
----------------------------------------------------------------------
diff --cc gateway-discovery-ambari/src/test/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryTest.java
index ec8aed2,0000000..21627ad
mode 100644,000000..100644
--- a/gateway-discovery-ambari/src/test/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryTest.java
+++ b/gateway-discovery-ambari/src/test/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscoveryTest.java
@@@ -1,856 -1,0 +1,858 @@@
 +/**
 + * 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.ambari;
 +
 +import net.minidev.json.JSONObject;
 +import net.minidev.json.JSONValue;
 +import org.apache.knox.gateway.topology.discovery.ServiceDiscovery;
 +import org.apache.knox.gateway.topology.discovery.ServiceDiscoveryConfig;
 +import org.easymock.EasyMock;
 +import org.junit.Test;
 +
 +import java.util.HashMap;
 +import java.util.List;
 +import java.util.Map;
 +
- import static org.junit.Assert.*;
++import static org.junit.Assert.assertNotNull;
++import static org.junit.Assert.assertEquals;
++import static org.junit.Assert.assertTrue;
 +
 +
 +/**
 + * Test the Ambari ServiceDiscovery implementation.
 + *
 + * N.B. These tests do NOT verify Ambari API responses. They DO validate the Ambari ServiceDiscovery implementation's
 + *      treatment of the responses as they were observed at the time the tests are developed.
 + */
 +public class AmbariServiceDiscoveryTest {
 +
 +    @Test
 +    public void testSingleClusterDiscovery() throws Exception {
 +        final String discoveryAddress = "http://ambarihost:8080";
 +        final String clusterName = "testCluster";
 +        ServiceDiscovery sd = new TestAmbariServiceDiscovery(clusterName);
 +
 +        ServiceDiscoveryConfig sdc = EasyMock.createNiceMock(ServiceDiscoveryConfig.class);
 +        EasyMock.expect(sdc.getAddress()).andReturn(discoveryAddress).anyTimes();
 +        EasyMock.expect(sdc.getUser()).andReturn(null).anyTimes();
 +        EasyMock.replay(sdc);
 +
 +        ServiceDiscovery.Cluster cluster = sd.discover(sdc, clusterName);
 +        assertNotNull(cluster);
 +        assertEquals(clusterName, cluster.getName());
 +        assertTrue(AmbariCluster.class.isAssignableFrom(cluster.getClass()));
 +        assertEquals(6, ((AmbariCluster) cluster).getComponents().size());
 +
 +//        printServiceURLs(cluster);
 +    }
 +
 +
 +    @Test
 +    public void testBulkClusterDiscovery() throws Exception {
 +        final String discoveryAddress = "http://ambarihost:8080";
 +        final String clusterName = "anotherCluster";
 +        ServiceDiscovery sd = new TestAmbariServiceDiscovery(clusterName);
 +
 +        ServiceDiscoveryConfig sdc = EasyMock.createNiceMock(ServiceDiscoveryConfig.class);
 +        EasyMock.expect(sdc.getAddress()).andReturn(discoveryAddress).anyTimes();
 +        EasyMock.expect(sdc.getUser()).andReturn(null).anyTimes();
 +        EasyMock.replay(sdc);
 +
 +        Map<String, ServiceDiscovery.Cluster> clusters = sd.discover(sdc);
 +        assertNotNull(clusters);
 +        assertEquals(1, clusters.size());
 +        ServiceDiscovery.Cluster cluster = clusters.get(clusterName);
 +        assertNotNull(cluster);
 +        assertEquals(clusterName, cluster.getName());
 +        assertTrue(AmbariCluster.class.isAssignableFrom(cluster.getClass()));
 +        assertEquals(6, ((AmbariCluster) cluster).getComponents().size());
 +
 +//        printServiceURLs(cluster, "NAMENODE", "WEBHCAT", "OOZIE", "RESOURCEMANAGER");
 +    }
 +
 +
 +    private static void printServiceURLs(ServiceDiscovery.Cluster cluster) {
 +        final String[] services = new String[]{"NAMENODE",
 +                                               "JOBTRACKER",
 +                                               "WEBHDFS",
 +                                               "WEBHCAT",
 +                                               "OOZIE",
 +                                               "WEBHBASE",
 +                                               "HIVE",
 +                                               "RESOURCEMANAGER"};
 +        printServiceURLs(cluster, services);
 +    }
 +
 +
 +    private static void printServiceURLs(ServiceDiscovery.Cluster cluster, String...services) {
 +        for (String name : services) {
 +            StringBuilder sb = new StringBuilder();
 +            List<String> urls = cluster.getServiceURLs(name);
 +            if (urls != null && !urls.isEmpty()) {
 +                for (String url : urls) {
 +                    sb.append(url);
 +                    sb.append(" ");
 +                }
 +            }
 +            System.out.println(String.format("%18s: %s", name, sb.toString()));
 +        }
 +    }
 +
 +
 +    /**
 +     * ServiceDiscovery implementation derived from AmbariServiceDiscovery, so the invokeREST method can be overridden
 +     * to eliminate the need to perform actual HTTP interactions with a real Ambari endpoint.
 +     */
 +    private static final class TestAmbariServiceDiscovery extends AmbariServiceDiscovery {
 +
 +        final static String CLUSTER_PLACEHOLDER = "CLUSTER_NAME";
 +
 +        private Map<String, JSONObject> cannedResponses = new HashMap<>();
 +
 +        TestAmbariServiceDiscovery(String clusterName) {
 +            cannedResponses.put(AMBARI_CLUSTERS_URI,
 +                                (JSONObject) JSONValue.parse(CLUSTERS_JSON_TEMPLATE.replaceAll(CLUSTER_PLACEHOLDER,
 +                                                                                               clusterName)));
 +
 +            cannedResponses.put(String.format(AMBARI_HOSTROLES_URI, clusterName),
 +                                (JSONObject) JSONValue.parse(HOSTROLES_JSON_TEMPLATE.replaceAll(CLUSTER_PLACEHOLDER,
 +                                                                                                clusterName)));
 +
 +            cannedResponses.put(String.format(AMBARI_SERVICECONFIGS_URI, clusterName),
 +                                (JSONObject) JSONValue.parse(SERVICECONFIGS_JSON_TEMPLATE.replaceAll(CLUSTER_PLACEHOLDER,
 +                                                                                                     clusterName)));
 +        }
 +
 +        @Override
 +        protected JSONObject invokeREST(String url, String username, String passwordAlias) {
 +            return cannedResponses.get(url.substring(url.indexOf("/api")));
 +        }
 +    }
 +
 +
 +    ////////////////////////////////////////////////////////////////////////
 +    //  JSON response templates, based on actual response content excerpts
 +    ////////////////////////////////////////////////////////////////////////
 +
 +    private static final String CLUSTERS_JSON_TEMPLATE =
 +    "{\n" +
 +    "  \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters\",\n" +
 +    "  \"items\" : [\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "      \"Clusters\" : {\n" +
 +    "        \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "        \"version\" : \"HDP-2.6\"\n" +
 +    "      }\n" +
 +    "    }\n" +
 +    "  ]" +
 +    "}";
 +
 +
 +    private static final String HOSTROLES_JSON_TEMPLATE =
 +    "{\n" +
 +    "  \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services?fields=components/host_components/HostRoles\",\n" +
 +    "  \"items\" : [\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/AMBARI_METRICS\",\n" +
 +    "      \"ServiceInfo\" : {\n" +
 +    "        \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "        \"service_name\" : \"AMBARI_METRICS\"\n" +
 +    "      },\n" +
 +    "      \"components\" : [\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/AMBARI_METRICS/components/METRICS_COLLECTOR\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"METRICS_COLLECTOR\",\n" +
 +    "            \"service_name\" : \"AMBARI_METRICS\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6403.ambari.apache.org/host_components/METRICS_COLLECTOR\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"METRICS_COLLECTOR\",\n" +
 +    "                \"host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"AMBARI_METRICS\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HBASE/components/HBASE_MASTER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"HBASE_MASTER\",\n" +
 +    "            \"service_name\" : \"HBASE\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6401.ambari.apache.org/host_components/HBASE_MASTER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"HBASE_MASTER\",\n" +
 +    "                \"host_name\" : \"c6401.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6401.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"HBASE\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        }\n" +
 +    "      ]\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HDFS\",\n" +
 +    "      \"ServiceInfo\" : {\n" +
 +    "        \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "        \"service_name\" : \"HDFS\"\n" +
 +    "      },\n" +
 +    "      \"components\" : [\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HDFS/components/NAMENODE\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"NAMENODE\",\n" +
 +    "            \"service_name\" : \"HDFS\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6401.ambari.apache.org/host_components/NAMENODE\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"NAMENODE\",\n" +
 +    "                \"host_name\" : \"c6401.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6401.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"HDFS\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HDFS/components/SECONDARY_NAMENODE\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"SECONDARY_NAMENODE\",\n" +
 +    "            \"service_name\" : \"HDFS\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/SECONDARY_NAMENODE\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"SECONDARY_NAMENODE\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"HDFS\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        }\n" +
 +    "      ]\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HIVE\",\n" +
 +    "      \"ServiceInfo\" : {\n" +
 +    "        \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "        \"service_name\" : \"HIVE\"\n" +
 +    "      },\n" +
 +    "      \"components\" : [\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HIVE/components/HCAT\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"HCAT\",\n" +
 +    "            \"service_name\" : \"HIVE\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6403.ambari.apache.org/host_components/HCAT\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"HCAT\",\n" +
 +    "                \"host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"HIVE\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        }\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HIVE/components/HIVE_METASTORE\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"HIVE_METASTORE\",\n" +
 +    "            \"service_name\" : \"HIVE\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/HIVE_METASTORE\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"HIVE_METASTORE\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"HIVE\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HIVE/components/HIVE_SERVER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"HIVE_SERVER\",\n" +
 +    "            \"service_name\" : \"HIVE\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/HIVE_SERVER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"HIVE_SERVER\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"HIVE\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/HIVE/components/WEBHCAT_SERVER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"WEBHCAT_SERVER\",\n" +
 +    "            \"service_name\" : \"HIVE\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/WEBHCAT_SERVER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"WEBHCAT_SERVER\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"HIVE\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\",\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        }\n" +
 +    "      ]\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/OOZIE\",\n" +
 +    "      \"ServiceInfo\" : {\n" +
 +    "        \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "        \"service_name\" : \"OOZIE\"\n" +
 +    "      },\n" +
 +    "      \"components\" : [\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/OOZIE/components/OOZIE_SERVER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"OOZIE_SERVER\",\n" +
 +    "            \"service_name\" : \"OOZIE\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/OOZIE_SERVER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"OOZIE_SERVER\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"OOZIE\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\"\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        }\n" +
 +    "      ]\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/YARN\",\n" +
 +    "      \"ServiceInfo\" : {\n" +
 +    "        \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "        \"service_name\" : \"YARN\"\n" +
 +    "      },\n" +
 +    "      \"components\" : [\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/YARN/components/APP_TIMELINE_SERVER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"APP_TIMELINE_SERVER\",\n" +
 +    "            \"service_name\" : \"YARN\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/APP_TIMELINE_SERVER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"APP_TIMELINE_SERVER\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"YARN\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\"\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/YARN/components/NODEMANAGER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"NODEMANAGER\",\n" +
 +    "            \"service_name\" : \"YARN\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6403.ambari.apache.org/host_components/NODEMANAGER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"NODEMANAGER\",\n" +
 +    "                \"host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"YARN\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\"\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/YARN/components/RESOURCEMANAGER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"RESOURCEMANAGER\",\n" +
 +    "            \"service_name\" : \"YARN\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/RESOURCEMANAGER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"RESOURCEMANAGER\",\n" +
 +    "                \"ha_state\" : \"ACTIVE\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"YARN\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\"\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        }\n" +
 +    "      ]\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/ZOOKEEPER\",\n" +
 +    "      \"ServiceInfo\" : {\n" +
 +    "        \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "        \"service_name\" : \"ZOOKEEPER\"\n" +
 +    "      },\n" +
 +    "      \"components\" : [\n" +
 +    "        {\n" +
 +    "          \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/services/ZOOKEEPER/components/ZOOKEEPER_SERVER\",\n" +
 +    "          \"ServiceComponentInfo\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"component_name\" : \"ZOOKEEPER_SERVER\",\n" +
 +    "            \"service_name\" : \"ZOOKEEPER\"\n" +
 +    "          },\n" +
 +    "          \"host_components\" : [\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6401.ambari.apache.org/host_components/ZOOKEEPER_SERVER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"ZOOKEEPER_SERVER\",\n" +
 +    "                \"host_name\" : \"c6401.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6401.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"ZOOKEEPER\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\"\n" +
 +    "              }\n" +
 +    "            },\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6402.ambari.apache.org/host_components/ZOOKEEPER_SERVER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"ZOOKEEPER_SERVER\",\n" +
 +    "                \"host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6402.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"ZOOKEEPER\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\"\n" +
 +    "              }\n" +
 +    "            },\n" +
 +    "            {\n" +
 +    "              \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/hosts/c6403.ambari.apache.org/host_components/ZOOKEEPER_SERVER\",\n" +
 +    "              \"HostRoles\" : {\n" +
 +    "                \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "                \"component_name\" : \"ZOOKEEPER_SERVER\",\n" +
 +    "                \"host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"public_host_name\" : \"c6403.ambari.apache.org\",\n" +
 +    "                \"service_name\" : \"ZOOKEEPER\",\n" +
 +    "                \"stack_id\" : \"HDP-2.6\"\n" +
 +    "              }\n" +
 +    "            }\n" +
 +    "          ]\n" +
 +    "        }\n" +
 +    "      ]\n" +
 +    "    }\n" +
 +    "  ]\n" +
 +    "}\n";
 +
 +
 +    private static final String SERVICECONFIGS_JSON_TEMPLATE =
 +    "{\n" +
 +    "  \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/configurations/service_config_versions?is_current=true\",\n" +
 +    "  \"items\" : [\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/configurations/service_config_versions?service_name=HBASE&service_config_version=1\",\n" +
 +    "      \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "      \"configurations\" : [\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"hbase-site\",\n" +
 +    "          \"tag\" : \"version1503410563715\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"hbase.master.info.bindAddress\" : \"0.0.0.0\",\n" +
 +    "            \"hbase.master.info.port\" : \"16010\",\n" +
 +    "            \"hbase.master.port\" : \"16000\",\n" +
 +    "            \"hbase.regionserver.info.port\" : \"16030\",\n" +
 +    "            \"hbase.regionserver.port\" : \"16020\",\n" +
 +    "            \"hbase.zookeeper.property.clientPort\" : \"2181\",\n" +
 +    "            \"hbase.zookeeper.quorum\" : \"c6403.ambari.apache.org,c6402.ambari.apache.org,c6401.ambari.apache.org\",\n" +
 +    "            \"hbase.zookeeper.useMulti\" : \"true\",\n" +
 +    "            \"zookeeper.znode.parent\" : \"/hbase-unsecure\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        },\n" +
 +    "      ],\n" +
 +    "      \"is_current\" : true,\n" +
 +    "      \"service_config_version\" : 1,\n" +
 +    "      \"service_config_version_note\" : \"Initial configurations for HBase\",\n" +
 +    "      \"service_name\" : \"HBASE\",\n" +
 +    "      \"stack_id\" : \"HDP-2.6\",\n" +
 +    "      \"user\" : \"admin\"\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/configurations/service_config_versions?service_name=HDFS&service_config_version=2\",\n" +
 +    "      \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "      \"configurations\" : [\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"hdfs-site\",\n" +
 +    "          \"tag\" : \"version1\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"dfs.cluster.administrators\" : \" hdfs\",\n" +
 +    "            \"dfs.datanode.address\" : \"0.0.0.0:50010\",\n" +
 +    "            \"dfs.datanode.http.address\" : \"0.0.0.0:50075\",\n" +
 +    "            \"dfs.datanode.https.address\" : \"0.0.0.0:50475\",\n" +
 +    "            \"dfs.datanode.ipc.address\" : \"0.0.0.0:8010\",\n" +
 +    "            \"dfs.http.policy\" : \"HTTP_ONLY\",\n" +
 +    "            \"dfs.https.port\" : \"50470\",\n" +
 +    "            \"dfs.journalnode.http-address\" : \"0.0.0.0:8480\",\n" +
 +    "            \"dfs.journalnode.https-address\" : \"0.0.0.0:8481\",\n" +
 +    "            \"dfs.namenode.http-address\" : \"c6401.ambari.apache.org:50070\",\n" +
 +    "            \"dfs.namenode.https-address\" : \"c6401.ambari.apache.org:50470\",\n" +
 +    "            \"dfs.namenode.rpc-address\" : \"c6401.ambari.apache.org:8020\",\n" +
 +    "            \"dfs.namenode.secondary.http-address\" : \"c6402.ambari.apache.org:50090\",\n" +
 +    "            \"dfs.webhdfs.enabled\" : \"true\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : {\n" +
 +    "            \"final\" : {\n" +
 +    "              \"dfs.webhdfs.enabled\" : \"true\",\n" +
 +    "              \"dfs.namenode.http-address\" : \"true\",\n" +
 +    "              \"dfs.support.append\" : \"true\",\n" +
 +    "              \"dfs.namenode.name.dir\" : \"true\",\n" +
 +    "              \"dfs.datanode.failed.volumes.tolerated\" : \"true\",\n" +
 +    "              \"dfs.datanode.data.dir\" : \"true\"\n" +
 +    "            }\n" +
 +    "          }\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"core-site\",\n" +
 +    "          \"tag\" : \"version1502131215159\",\n" +
 +    "          \"version\" : 2,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"hadoop.http.authentication.simple.anonymous.allowed\" : \"true\",\n" +
 +    "            \"net.topology.script.file.name\" : \"/etc/hadoop/conf/topology_script.py\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : {\n" +
 +    "            \"final\" : {\n" +
 +    "              \"fs.defaultFS\" : \"true\"\n" +
 +    "            }\n" +
 +    "          }\n" +
 +    "        }\n" +
 +    "      ],\n" +
 +    "      \"is_current\" : true,\n" +
 +    "      \"service_config_version\" : 2,\n" +
 +    "      \"service_config_version_note\" : \"knox trusted proxy support\",\n" +
 +    "      \"service_name\" : \"HDFS\",\n" +
 +    "      \"stack_id\" : \"HDP-2.6\",\n" +
 +    "      \"user\" : \"admin\"\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/configurations/service_config_versions?service_name=HIVE&service_config_version=3\",\n" +
 +    "      \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "      \"configurations\" : [\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"hive-env\",\n" +
 +    "          \"tag\" : \"version1\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"hive_security_authorization\" : \"None\",\n" +
 +    "            \"webhcat_user\" : \"hcat\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"hiveserver2-site\",\n" +
 +    "          \"tag\" : \"version1\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"hive.metastore.metrics.enabled\" : \"true\",\n" +
 +    "            \"hive.security.authorization.enabled\" : \"false\",\n" +
 +    "            \"hive.service.metrics.hadoop2.component\" : \"hiveserver2\",\n" +
 +    "            \"hive.service.metrics.reporter\" : \"HADOOP2\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"hive-interactive-site\",\n" +
 +    "          \"tag\" : \"version1\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"hive.server2.enable.doAs\" : \"false\",\n" +
 +    "            \"hive.server2.tez.default.queues\" : \"default\",\n" +
 +    "            \"hive.server2.tez.initialize.default.sessions\" : \"true\",\n" +
 +    "            \"hive.server2.tez.sessions.custom.queue.allowed\" : \"ignore\",\n" +
 +    "            \"hive.server2.tez.sessions.per.default.queue\" : \"1\",\n" +
 +    "            \"hive.server2.tez.sessions.restricted.configs\" : \"hive.execution.mode,hive.execution.engine\",\n" +
 +    "            \"hive.server2.thrift.http.port\" : \"10501\",\n" +
 +    "            \"hive.server2.thrift.port\" : \"10500\",\n" +
 +    "            \"hive.server2.webui.port\" : \"10502\",\n" +
 +    "            \"hive.server2.webui.use.ssl\" : \"false\",\n" +
 +    "            \"hive.server2.zookeeper.namespace\" : \"hiveserver2-hive2\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"tez-interactive-site\",\n" +
 +    "          \"tag\" : \"version1\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"tez.am.am-rm.heartbeat.interval-ms.max\" : \"10000\",\n" +
 +    "            \"tez.am.client.heartbeat.poll.interval.millis\" : \"6000\",\n" +
 +    "            \"tez.am.client.heartbeat.timeout.secs\" : \"90\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"hive-site\",\n" +
 +    "          \"tag\" : \"version1502130841736\",\n" +
 +    "          \"version\" : 2,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"hive.metastore.sasl.enabled\" : \"false\",\n" +
 +    "            \"hive.metastore.server.max.threads\" : \"100000\",\n" +
 +    "            \"hive.metastore.uris\" : \"thrift://c6402.ambari.apache.org:9083\",\n" +
 +    "            \"hive.server2.allow.user.substitution\" : \"true\",\n" +
 +    "            \"hive.server2.authentication\" : \"NONE\",\n" +
 +    "            \"hive.server2.authentication.spnego.keytab\" : \"HTTP/_HOST@EXAMPLE.COM\",\n" +
 +    "            \"hive.server2.authentication.spnego.principal\" : \"/etc/security/keytabs/spnego.service.keytab\",\n" +
 +    "            \"hive.server2.enable.doAs\" : \"true\",\n" +
 +    "            \"hive.server2.support.dynamic.service.discovery\" : \"true\",\n" +
 +    "            \"hive.server2.thrift.http.path\" : \"cliservice\",\n" +
 +    "            \"hive.server2.thrift.http.port\" : \"10001\",\n" +
 +    "            \"hive.server2.thrift.max.worker.threads\" : \"500\",\n" +
 +    "            \"hive.server2.thrift.port\" : \"10000\",\n" +
 +    "            \"hive.server2.thrift.sasl.qop\" : \"auth\",\n" +
 +    "            \"hive.server2.transport.mode\" : \"http\",\n" +
 +    "            \"hive.server2.use.SSL\" : \"false\",\n" +
 +    "            \"hive.server2.zookeeper.namespace\" : \"hiveserver2\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : {\n" +
 +    "            \"hidden\" : {\n" +
 +    "              \"javax.jdo.option.ConnectionPassword\" : \"HIVE_CLIENT,WEBHCAT_SERVER,HCAT,CONFIG_DOWNLOAD\"\n" +
 +    "            }\n" +
 +    "          }\n" +
 +    "        },\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"webhcat-site\",\n" +
 +    "          \"tag\" : \"version1502131111746\",\n" +
 +    "          \"version\" : 2,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"templeton.port\" : \"50111\",\n" +
 +    "            \"templeton.zookeeper.hosts\" : \"c6403.ambari.apache.org:2181,c6401.ambari.apache.org:2181,c6402.ambari.apache.org:2181\",\n" +
 +    "            \"webhcat.proxyuser.knox.groups\" : \"users\",\n" +
 +    "            \"webhcat.proxyuser.knox.hosts\" : \"*\",\n" +
 +    "            \"webhcat.proxyuser.root.groups\" : \"*\",\n" +
 +    "            \"webhcat.proxyuser.root.hosts\" : \"c6401.ambari.apache.org\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        }\n" +
 +    "      ],\n" +
 +    "      \"createtime\" : 1502131110745,\n" +
 +    "      \"group_id\" : -1,\n" +
 +    "      \"group_name\" : \"Default\",\n" +
 +    "      \"hosts\" : [ ],\n" +
 +    "      \"is_cluster_compatible\" : true,\n" +
 +    "      \"is_current\" : true,\n" +
 +    "      \"service_config_version\" : 3,\n" +
 +    "      \"service_config_version_note\" : \"knox trusted proxy support\",\n" +
 +    "      \"service_name\" : \"HIVE\",\n" +
 +    "      \"stack_id\" : \"HDP-2.6\",\n" +
 +    "      \"user\" : \"admin\"\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/configurations/service_config_versions?service_name=OOZIE&service_config_version=3\",\n" +
 +    "      \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "      \"configurations\" : [\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"oozie-site\",\n" +
 +    "          \"tag\" : \"version1502131137103\",\n" +
 +    "          \"version\" : 3,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"oozie.base.url\" : \"http://c6402.ambari.apache.org:11000/oozie\",\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        }\n" +
 +    "      ],\n" +
 +    "      \"is_current\" : true,\n" +
 +    "      \"service_config_version\" : 3,\n" +
 +    "      \"service_name\" : \"OOZIE\",\n" +
 +    "      \"stack_id\" : \"HDP-2.6\",\n" +
 +    "      \"user\" : \"admin\"\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/configurations/service_config_versions?service_name=TEZ&service_config_version=1\",\n" +
 +    "      \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "      \"configurations\" : [\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"tez-site\",\n" +
 +    "          \"tag\" : \"version1\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"tez.use.cluster.hadoop-libs\" : \"false\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        }\n" +
 +    "      ],\n" +
 +    "      \"createtime\" : 1502122253525,\n" +
 +    "      \"group_id\" : -1,\n" +
 +    "      \"group_name\" : \"Default\",\n" +
 +    "      \"hosts\" : [ ],\n" +
 +    "      \"is_cluster_compatible\" : true,\n" +
 +    "      \"is_current\" : true,\n" +
 +    "      \"service_config_version\" : 1,\n" +
 +    "      \"service_config_version_note\" : \"Initial configurations for Tez\",\n" +
 +    "      \"service_name\" : \"TEZ\",\n" +
 +    "      \"stack_id\" : \"HDP-2.6\",\n" +
 +    "      \"user\" : \"admin\"\n" +
 +    "    },\n" +
 +    "    {\n" +
 +    "      \"href\" : \"http://c6401.ambari.apache.org:8080/api/v1/clusters/"+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"/configurations/service_config_versions?service_name=YARN&service_config_version=1\",\n" +
 +    "      \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "      \"configurations\" : [\n" +
 +    "        {\n" +
 +    "          \"Config\" : {\n" +
 +    "            \"cluster_name\" : \""+TestAmbariServiceDiscovery.CLUSTER_PLACEHOLDER+"\",\n" +
 +    "            \"stack_id\" : \"HDP-2.6\"\n" +
 +    "          },\n" +
 +    "          \"type\" : \"yarn-site\",\n" +
 +    "          \"tag\" : \"version1\",\n" +
 +    "          \"version\" : 1,\n" +
 +    "          \"properties\" : {\n" +
 +    "            \"hadoop.registry.rm.enabled\" : \"true\",\n" +
 +    "            \"hadoop.registry.zk.quorum\" : \"c6403.ambari.apache.org:2181,c6401.ambari.apache.org:2181,c6402.ambari.apache.org:2181\",\n" +
 +    "            \"yarn.acl.enable\" : \"false\",\n" +
 +    "            \"yarn.http.policy\" : \"HTTP_ONLY\",\n" +
 +    "            \"yarn.nodemanager.address\" : \"0.0.0.0:45454\",\n" +
 +    "            \"yarn.nodemanager.bind-host\" : \"0.0.0.0\",\n" +
 +    "            \"yarn.resourcemanager.address\" : \"c6402.ambari.apache.org:8050\",\n" +
 +    "            \"yarn.resourcemanager.admin.address\" : \"c6402.ambari.apache.org:8141\",\n" +
 +    "            \"yarn.resourcemanager.ha.enabled\" : \"false\",\n" +
 +    "            \"yarn.resourcemanager.hostname\" : \"c6402.ambari.apache.org\",\n" +
 +    "            \"yarn.resourcemanager.resource-tracker.address\" : \"c6402.ambari.apache.org:8025\",\n" +
 +    "            \"yarn.resourcemanager.scheduler.address\" : \"c6402.ambari.apache.org:8030\",\n" +
 +    "            \"yarn.resourcemanager.webapp.address\" : \"c6402.ambari.apache.org:8088\",\n" +
 +    "            \"yarn.resourcemanager.webapp.delegation-token-auth-filter.enabled\" : \"false\",\n" +
 +    "            \"yarn.resourcemanager.webapp.https.address\" : \"c6402.ambari.apache.org:8090\",\n" +
 +    "            \"yarn.resourcemanager.zk-address\" : \"c6403.ambari.apache.org:2181,c6401.ambari.apache.org:2181,c6402.ambari.apache.org:2181\"\n" +
 +    "          },\n" +
 +    "          \"properties_attributes\" : { }\n" +
 +    "        }\n" +
 +    "      ],\n" +
 +    "      \"is_current\" : true,\n" +
 +    "      \"service_config_version\" : 1,\n" +
 +    "      \"service_name\" : \"YARN\",\n" +
 +    "      \"stack_id\" : \"HDP-2.6\",\n" +
 +    "      \"user\" : \"admin\"\n" +
 +    "    }\n" +
 +    "  ]\n" +
 +    "}";
 +
 +}