package io.fathom.auto.config; import io.fathom.auto.TimeSpan; import java.util.Collection; import java.util.Collections; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Maps; public abstract class ConfigStore { public static final String KEY_DNS_HOST = "__dns:host"; private static final Logger log = LoggerFactory.getLogger(ConfigStore.class); ConfigPath root; protected ConfigStore() { } public abstract void init(); static final Map<String, String> WELL_KNOWN_PROVIDERS; static { WELL_KNOWN_PROVIDERS = Maps.newLinkedHashMap(); WELL_KNOWN_PROVIDERS.put("etcd", "io.fathom.auto.config.EtcdConfigStoreProvider"); WELL_KNOWN_PROVIDERS.put("openstack", "io.fathom.auto.config.OpenstackConfigStoreProvider"); } public static ConfigStore get(String serviceKey) { while (true) { try { String configStoreProperty = System.getProperty("configStore"); String configClass = null; Collection<String> classes = WELL_KNOWN_PROVIDERS.values(); if (configStoreProperty != null) { configClass = WELL_KNOWN_PROVIDERS.get(configStoreProperty); if (configClass == null) { // Assume it's a class name configClass = configStoreProperty; } classes = Collections.singletonList(configClass); } for (String className : classes) { ConfigStoreProvider configStoreProvider = null; try { Class<?> providerClass = Class.forName(className); configStoreProvider = (ConfigStoreProvider) providerClass.newInstance(); } catch (Exception e) { log.warn("Error loading config provider: " + className, e); } ConfigStore config = null; if (configStoreProvider != null) { config = get(configStoreProvider, serviceKey); } if (config != null) { config.init(); return config; } } log.warn("Unable to determine config; waiting and retrying"); } catch (Exception e) { log.warn("Error buildling configuration store", e); } TimeSpan.seconds(5).sleep(); } } public static ConfigStore get(ConfigStoreProvider configStoreProvider, String serviceKey) { ConfigStore config = null; try { if (configStoreProvider.init()) { String clusterKey = "__default"; String basePath = configStoreProvider.getInstanceProperty("configStorePath"); if (basePath == null) { // TODO: Support multiple clusters? basePath = clusterKey + "/"; } else { if (!basePath.endsWith("/")) { basePath += "/"; } } try { config = configStoreProvider.build(clusterKey, basePath, serviceKey); } catch (Exception e) { log.warn("Error loading config from: " + configStoreProvider.getClass().getSimpleName(), e); } } if (config != null) { config.init(); return config; } log.warn("Unable to determine config; waiting and retrying"); } catch (Exception e) { log.warn("Error buildling configuration store", e); } return config; } public static abstract class ConfigStoreProvider { protected abstract ConfigStore build(String clusterKey, String basePath, String serviceKey); public abstract String getInstanceProperty(String key); public abstract boolean init(); } public synchronized ConfigPath getConfigRoot() { if (root == null) { root = getConfigRoot0(); } return root; } protected abstract ConfigPath getConfigRoot0(); public abstract ConfigPath getSharedPath(String key); public abstract String getClusterKey(); public abstract SecretKeys getSecretKeys(); public abstract String getInstanceProperty(String key); }