Skip to content

Commit

Permalink
Merge 5977c32 into 41049be
Browse files Browse the repository at this point in the history
  • Loading branch information
yhs0092 committed Apr 19, 2018
2 parents 41049be + 5977c32 commit b6c67ce
Show file tree
Hide file tree
Showing 19 changed files with 632 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -55,6 +56,16 @@ public final class ConfigUtil {

private static Map<String, Object> localConfig = new HashMap<>();

/**
* <p>The configurations not read by ServiceComb.</p>
* <p>
* For example, this map can store the configurations read by SpringBoot from application.properties,
* If users write the configurations of ServiceComb into application.yml instead of microservice.yaml,
* this can help {@link ConfigUtil} load config correctly.
* </p>
*/
private static final Map<String, Map<String, Object>> EXTRA_CONFIG_MAP = new LinkedHashMap<>();

private ConfigUtil() {
}

Expand Down Expand Up @@ -110,8 +121,6 @@ public static ConcurrentCompositeConfiguration createLocalConfig() {
return config;
}



public static ConcurrentCompositeConfiguration createLocalConfig(List<ConfigModel> configModelList) {
ConcurrentCompositeConfiguration config = new ConcurrentCompositeConfiguration();

Expand All @@ -125,6 +134,13 @@ public static ConcurrentCompositeConfiguration createLocalConfig(List<ConfigMode
new DynamicConfiguration(
new MicroserviceConfigurationSource(configModelList), new NeverStartPollingScheduler()),
"configFromYamlFile");
// If there is extra configurations, add it into config. Extra config has lowest priority.
EXTRA_CONFIG_MAP.entrySet().stream()
.filter(mapEntry -> !mapEntry.getValue().isEmpty())
.forEachOrdered(configMapEntry ->
duplicateServiceCombConfigToCse(config,
new ConcurrentMapConfiguration(configMapEntry.getValue()),
configMapEntry.getKey()));

return config;
}
Expand Down Expand Up @@ -210,6 +226,14 @@ public static void installDynamicConfig() {
ConfigurationManager.install(dynamicConfig);
}

public static void addExtraConfig(String extraConfigName, Map<String, Object> extraConfig) {
EXTRA_CONFIG_MAP.put(extraConfigName, extraConfig);
}

public static void clearExtraConfig() {
EXTRA_CONFIG_MAP.clear();
}

private static class ServiceCombPropertyUpdateListener implements WatchedUpdateListener {

private final ConcurrentMapConfiguration injectConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,53 @@
package org.apache.servicecomb.config;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.configuration.AbstractConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;

import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicPropertyFactory;

public class ConfigurationSpringInitializer extends PropertyPlaceholderConfigurer {
public class ConfigurationSpringInitializer extends PropertyPlaceholderConfigurer implements EnvironmentAware {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationSpringInitializer.class);

public static final String EXTRA_CONFIG_SOURCE_PREFIX = "extraConfig-";

public ConfigurationSpringInitializer() {
ConfigUtil.installDynamicConfig();
setOrder(Ordered.LOWEST_PRECEDENCE / 2);
setIgnoreUnresolvablePlaceholders(true);
}

/**
* Get configurations from Spring, merge them into the configurations of ServiceComb.
* @param environment From which to get the extra config.
*/
@Override
public void setEnvironment(Environment environment) {
String environmentName = generateNameForEnvironment(environment);
LOGGER.info("Environment received, will get configurations from [{}].", environmentName);

Map<String, Object> extraConfig = getAllProperties(environment);

ConfigUtil.addExtraConfig(EXTRA_CONFIG_SOURCE_PREFIX + environmentName, extraConfig);

ConfigUtil.installDynamicConfig();
}

@Override
protected Properties mergeProperties() throws IOException {
Properties properties = super.mergeProperties();
Expand All @@ -57,4 +87,62 @@ protected String resolvePlaceholder(String placeholder, Properties props) {
}
return propertyValue;
}

/**
* Try to get a name for identifying the environment.
* @param environment the target that the name is generated for.
* @return The generated name for the environment.
*/
private String generateNameForEnvironment(Environment environment) {
String environmentName = environment.getProperty("spring.config.name");
if (!StringUtils.isEmpty(environmentName)) {
return environmentName;
}

environmentName = environment.getProperty("spring.application.name");
if (!StringUtils.isEmpty(environmentName)) {
return environmentName;
}

return environment.getClass().getName() + "@" + environment.hashCode();
}

/**
* Traversal all {@link PropertySource} of {@link ConfigurableEnvironment}, and try to get all properties.
*/
private Map<String, Object> getAllProperties(Environment environment) {
Map<String, Object> configFromSpringBoot = new HashMap<>();

if (!(environment instanceof ConfigurableEnvironment)) {
return configFromSpringBoot;
}

ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment;
for (PropertySource<?> propertySource : configurableEnvironment.getPropertySources()) {
getProperties(configurableEnvironment, propertySource, configFromSpringBoot);
}
return configFromSpringBoot;
}

/**
* Get property names from {@link EnumerablePropertySource}, and get property value from {@link ConfigurableEnvironment#getProperty(String)}
*/
private void getProperties(ConfigurableEnvironment environment, PropertySource<?> propertySource,
Map<String, Object> configFromSpringBoot) {
if (propertySource instanceof CompositePropertySource) {
// recursively get EnumerablePropertySource
CompositePropertySource compositePropertySource = (CompositePropertySource) propertySource;
compositePropertySource.getPropertySources().forEach(ps -> getProperties(environment, ps, configFromSpringBoot));
return;
}
if (propertySource instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) propertySource;
for (String propertyName : enumerablePropertySource.getPropertyNames()) {
configFromSpringBoot.put(propertyName, environment.getProperty(propertyName));
}
return;
}

LOGGER.debug("a none EnumerablePropertySource is ignored, propertySourceName = [{}]", propertySource.getName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,28 @@
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

import com.netflix.config.*;
import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.servicecomb.config.archaius.sources.ConfigModel;
import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader;
import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource;
import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.DynamicConfiguration;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicWatchedConfiguration;

import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Mocked;
Expand Down Expand Up @@ -73,21 +78,21 @@ public static void beforeTest() {
}

@AfterClass
public static void tearDown() throws Exception {
public static void tearDown() {
ArchaiusUtils.resetConfig();
}

@Test
public void testAddConfig() {
Map config = new HashMap<String, Object>();
Map<String, Object> config = new HashMap<>();
config.put("service_description.name", "service_name_test");
ConfigUtil.setConfigs(config);
ConfigUtil.addConfig("service_description.version", "1.0.2");
ConfigUtil.addConfig("cse.test.enabled", true);
ConfigUtil.addConfig("cse.test.num", 10);
AbstractConfiguration configuration = ConfigUtil.createDynamicConfig();
Assert.assertEquals(configuration.getString("service_description.name"), "service_name_test");
Assert.assertEquals(configuration.getBoolean("cse.test.enabled"), true);
Assert.assertTrue(configuration.getBoolean("cse.test.enabled"));
Assert.assertEquals(configuration.getInt("cse.test.num"), 10);
}

Expand Down Expand Up @@ -116,8 +121,7 @@ public void testCreateDynamicConfigNoConfigCenterSPI() {
}

@Test
public void testCreateDynamicConfigHasConfigCenter(
@Mocked ConfigCenterConfigurationSource configCenterConfigurationSource) {
public void testCreateDynamicConfigHasConfigCenter() {
AbstractConfiguration dynamicConfig = ConfigUtil.createDynamicConfig();
Assert.assertEquals(DynamicWatchedConfiguration.class,
((ConcurrentCompositeConfiguration) dynamicConfig).getConfiguration(0).getClass());
Expand All @@ -130,54 +134,54 @@ public void testGetPropertyInvalidConfig() {
}

@Test
public void propertiesFromFileIsDuplicatedToCse() throws Exception {
public void propertiesFromFileIsDuplicatedToCse() {
String expected = "value";

assertThat(DynamicPropertyFactory
.getInstance()
.getStringProperty("servicecomb.cse.servicecomb.file", null)
.get(),
.getInstance()
.getStringProperty("servicecomb.cse.servicecomb.file", null)
.get(),
equalTo(expected));

assertThat(DynamicPropertyFactory
.getInstance()
.getStringProperty("cse.cse.servicecomb.file", null)
.get(),
.getInstance()
.getStringProperty("cse.cse.servicecomb.file", null)
.get(),
equalTo(expected));
}

@Test
public void propertiesFromSystemIsDuplicatedToCse() throws Exception {
public void propertiesFromSystemIsDuplicatedToCse() {
assertThat(DynamicPropertyFactory
.getInstance()
.getStringProperty(systemPropertyName, null)
.get(),
.getInstance()
.getStringProperty(systemPropertyName, null)
.get(),
equalTo(systemExpected));

assertThat(DynamicPropertyFactory
.getInstance()
.getStringProperty("servicecomb.cse.servicecomb.system.setting", null)
.get(),
.getInstance()
.getStringProperty("servicecomb.cse.servicecomb.system.setting", null)
.get(),
equalTo(systemExpected));
}

@Test
public void propertiesFromEnvironmentIsDuplicatedToCse() throws Exception {
public void propertiesFromEnvironmentIsDuplicatedToCse() {
assertThat(DynamicPropertyFactory
.getInstance()
.getStringProperty(environmentPropertyName, null)
.get(),
.getInstance()
.getStringProperty(environmentPropertyName, null)
.get(),
equalTo(environmentExpected));

assertThat(DynamicPropertyFactory
.getInstance()
.getStringProperty("servicecomb.cse.servicecomb.environment.setting", null)
.get(),
.getInstance()
.getStringProperty("servicecomb.cse.servicecomb.environment.setting", null)
.get(),
equalTo(environmentExpected));
}

@Test
public void duplicateServiceCombConfigToCseListValue() throws Exception {
public void duplicateServiceCombConfigToCseListValue() {
List<String> list = Arrays.asList("a", "b");

AbstractConfiguration config = new DynamicConfiguration();
Expand All @@ -190,7 +194,7 @@ public void duplicateServiceCombConfigToCseListValue() throws Exception {
}

@Test
public void propertiesAddFromDynamicConfigSourceIsDuplicated() throws Exception {
public void propertiesAddFromDynamicConfigSourceIsDuplicated() {
String expected = uniquify("ran");
String someProperty = "servicecomb.cse.servicecomb.add";
String injectProperty = "cse.cse.servicecomb.add";
Expand Down Expand Up @@ -231,7 +235,7 @@ public void propertiesAddFromDynamicConfigSourceIsDuplicated() throws Exception
}

@Test
public void propertiesChangeFromDynamicConfigSourceIsDuplicated() throws Exception {
public void propertiesChangeFromDynamicConfigSourceIsDuplicated() {
String expected = uniquify("ran");
String someProperty = "servicecomb.cse.servicecomb.change";
String injectProperty = "cse.cse.servicecomb.change";
Expand Down Expand Up @@ -269,7 +273,7 @@ public void propertiesChangeFromDynamicConfigSourceIsDuplicated() throws Excepti
}

@Test
public void propertiesDeleteFromDynamicConfigSourceIsDuplicated() throws Exception {
public void propertiesDeleteFromDynamicConfigSourceIsDuplicated() {
String expected = uniquify("ran");
String someProperty = "servicecomb.cse.servicecomb.delete";
String injectProperty = "cse.cse.servicecomb.delete";
Expand Down Expand Up @@ -315,6 +319,23 @@ public void testConvertEnvVariable() {
assertThat(result.getString("cse_service_registry_address"), equalTo("testing"));
}

@Test
public void testCreateLocalConfigWithExtraConfig() {
Map<String, Object> extraConfig = new ConcurrentHashMapEx<>(1);
String extraConfigKey = "extraConfigKey";
String extraConfigValue = "value";
String overriddenConfigKey = "servicecomb.cse.servicecomb.file";
extraConfig.put(extraConfigKey, extraConfigValue);
extraConfig.put(overriddenConfigKey, "should_be_overridden");

ConfigUtil.addExtraConfig("testExtraConfig", extraConfig);

ConcurrentCompositeConfiguration localConfiguration = ConfigUtil.createLocalConfig();

Assert.assertEquals(extraConfigValue, localConfiguration.getProperty(extraConfigKey));
Assert.assertEquals("value", localConfiguration.getString(overriddenConfigKey));
}

@SuppressWarnings("unchecked")
private static void setEnv(String key, String value) throws IllegalAccessException, NoSuchFieldException {
Class<?>[] classes = Collections.class.getDeclaredClasses();
Expand Down

0 comments on commit b6c67ce

Please sign in to comment.