public Cluster discover()

in gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java [199:327]


    public Cluster discover(GatewayConfig gatewayConfig, ServiceDiscoveryConfig config, String clusterName) {
        AmbariCluster cluster = null;

        String discoveryAddress = config.getAddress();
        String discoveryUser = config.getUser();
        String discoveryPwdAlias = config.getPasswordAlias();

        // Handle missing discovery address value with the default if it has been defined
        if (discoveryAddress == null || discoveryAddress.isEmpty()) {
            discoveryAddress = gatewayConfig.getDefaultDiscoveryAddress();

            // If no default address could be determined
            if (discoveryAddress == null) {
                log.missingDiscoveryAddress();
            }
        }

        // Handle missing discovery cluster value with the default if it has been defined
        if (clusterName == null || clusterName.isEmpty()) {
            clusterName = gatewayConfig.getDefaultDiscoveryCluster();

            // If no default cluster could be determined
            if (clusterName == null) {
                log.missingDiscoveryCluster();
            }
        }

        // There must be a discovery address and cluster or discovery cannot be performed
        if (discoveryAddress != null && clusterName != null) {
            cluster = new AmbariCluster(clusterName);

            String encodedClusterName;
            try {
                encodedClusterName = URLEncoder.encode(clusterName, StandardCharsets.UTF_8.name());
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace(); // TODO: Logging
                encodedClusterName = clusterName;
            }

            Map<String, String> serviceComponents = new HashMap<>();

            init(gatewayConfig);

            Map<String, List<String>> componentHostNames = new HashMap<>();
            String hostRolesURL =
                        String.format(Locale.ROOT, "%s" + AMBARI_HOSTROLES_URI, discoveryAddress, encodedClusterName);
            JSONObject hostRolesJSON = restClient.invoke(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);

                            // 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<>());
                                }
                                // Avoid duplicates
                                if (!componentHostNames.get(componentName).contains(hostName)) {
                                    componentHostNames.get(componentName).add(hostName);
                                }
                            }
                        }
                    }
                }
            }

            // Service configurations
            Map<String, Map<String, AmbariCluster.ServiceConfiguration>> serviceConfigurations =
                ambariClient.getActiveServiceConfigurations(discoveryAddress,
                                                            encodedClusterName,
                                                            discoveryUser,
                                                            discoveryPwdAlias);
            if (serviceConfigurations.isEmpty()) {
                log.failedToAccessServiceConfigs(clusterName);
            }
            for (Entry<String, Map<String, AmbariCluster.ServiceConfiguration>> serviceConfiguration : serviceConfigurations.entrySet()) {
                for (Map.Entry<String, AmbariCluster.ServiceConfiguration> serviceConfig : serviceConfiguration.getValue().entrySet()) {
                    cluster.addServiceConfiguration(serviceConfiguration.getKey(), serviceConfig.getKey(), serviceConfig.getValue());
                }
            }

            // Construct the AmbariCluster model
            for (Entry<String, String> entry : serviceComponents.entrySet()) {
                String componentName = entry.getKey();
                String serviceName = entry.getValue();
                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);
                    if (svcConfig != null) {
                        AmbariComponent c = new AmbariComponent(componentName,
                                                                svcConfig.getVersion(),
                                                                encodedClusterName,
                                                                serviceName,
                                                                hostNames,
                                                                svcConfig.getProperties());
                        cluster.addComponent(c);
                    }
                }
            }

            if (configChangeMonitor != null) {
                // Notify the cluster config monitor about these cluster configuration details
                configChangeMonitor.addClusterConfigVersions(cluster, config);
            }
        }

        return cluster;
    }