org.apache.whirr.service.elasticsearch.ElasticSearchConfigurationBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.whirr.service.elasticsearch.ElasticSearchConfigurationBuilder.java

Source

/**
 * 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.whirr.service.elasticsearch;

import static org.apache.whirr.RolePredicates.role;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.lang.StringUtils;
import org.apache.whirr.Cluster;
import org.apache.whirr.ClusterSpec;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;
import org.slf4j.LoggerFactory;

public class ElasticSearchConfigurationBuilder {

    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ElasticSearchConfigurationBuilder.class);

    public static final String ES_PREFIX = "es";

    /**
     * Generate an appendFile statement for jclouds
     */
    public static Statement build(String path, Configuration config) {
        return asFileStatement(path, config);
    }

    public static Statement build(String path, ClusterSpec spec, Cluster cluster) {
        return build(path, buildConfig(spec, cluster));
    }

    /**
     * Build a configuration by adding the expected defaults
     */
    public static Configuration buildConfig(ClusterSpec spec, Cluster cluster) {
        CompositeConfiguration config = new CompositeConfiguration();

        config.addConfiguration(spec.getConfiguration());
        try {
            config.addConfiguration(new PropertiesConfiguration("whirr-elasticsearch-default.properties"));
        } catch (ConfigurationException e) {
            LOG.error("Configuration error", e); // this should never happen
        }

        if ("aws-ec2".equals(spec.getProvider()) || "ec2".equals(spec.getProvider())) {
            addDefaultsForEC2(spec, config);
        } else {
            addDefaultsForUnicast(cluster, config);
        }
        if (!config.containsKey("es.cluster.name")) {
            config.addProperty("es.cluster.name", spec.getClusterName());
        }

        return config;
    }

    /**
     * Use the native EC2 discovery module on AWS
     */
    private static void addDefaultsForEC2(ClusterSpec spec, CompositeConfiguration config) {
        config.addProperty("es.discovery.type", "ec2");
        if (!config.containsKey("es.cloud.aws.access_key")) {
            config.addProperty("es.cloud.aws.access_key", spec.getIdentity());
        }
        if (!config.containsKey("es.cloud.aws.secret_key")) {
            config.addProperty("es.cloud.aws.secret_key", spec.getCredential());
        }
        if (!config.getList("es.plugins", Lists.newLinkedList())
                .contains("elasticsearch/elasticsearch-cloud-aws/1.5.0")) {
            config.addProperty("es.plugins", "elasticsearch/elasticsearch-cloud-aws/1.5.0");
        }
    }

    /**
     * Use unicast if not on AWS (most of the cloud providers deny multicast traffic).
     */
    private static void addDefaultsForUnicast(Cluster cluster, CompositeConfiguration config) {
        List<String> hosts = Lists.newLinkedList();
        for (Cluster.Instance instance : cluster.getInstancesMatching(role(ElasticSearchHandler.ROLE))) {
            hosts.add(String.format("\"%s:9300\"", instance.getPrivateIp()));
        }
        config.addProperty("es.discovery.zen.ping.multicast.enabled", "false");
        config.addProperty("es.discovery.zen.ping.unicast.hosts", StringUtils.join(hosts, ","));
    }

    private static Statement asFileStatement(String path, Configuration configuration) {
        return Statements.appendFile(path, asYamlLines(configuration.subset(ES_PREFIX)));
    }

    /**
     * Create the YAML configuration file lines from the configuration.
     *
     * This functions transforms cloud.aws.id=1 to
     *
     * cloud:
     *   aws:
     *     id: 1
     */
    @VisibleForTesting
    public static List<String> asYamlLines(Configuration config) {
        return asYamlLines(config, 0);
    }

    private static List<String> asYamlLines(Configuration config, int depth) {
        List<String> lines = Lists.newArrayList();
        Set<String> prefixes = Sets.newHashSet();

        Iterator<String> keys = config.getKeys();
        while (keys.hasNext()) {
            String key = keys.next();

            String[] parts = key.split("\\.");
            String prefix = parts[0];

            if (prefixes.contains(prefix)) {
                continue; // skip parsed set of keys
            }

            if (parts.length == 1) {
                lines.add(spaces(depth * 2) + key + ": " + config.getProperty(key));

            } else if (parts.length > 1) {
                lines.add(spaces(depth * 2) + prefix + ":");
                lines.addAll(asYamlLines(config.subset(prefix), depth + 1));
            }

            prefixes.add(prefix);
        }

        return lines;
    }

    /**
     * Generate a string with spaces having the requested length
     */
    private static String spaces(int length) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            builder.append(" ");
        }
        return builder.toString();
    }
}