Merge branch '2.2.x'

This commit is contained in:
spencergibb
2020-09-28 11:18:35 -04:00
8 changed files with 164 additions and 18 deletions

View File

@@ -39,18 +39,22 @@ public class CompositeConfiguration {
private List<EnvironmentRepository> environmentRepos = new ArrayList<>();
private ConfigServerProperties properties;
@Bean
@Primary
@ConditionalOnBean(SearchPathLocator.class)
public SearchPathCompositeEnvironmentRepository searchPathCompositeEnvironmentRepository() {
return new SearchPathCompositeEnvironmentRepository(this.environmentRepos);
return new SearchPathCompositeEnvironmentRepository(this.environmentRepos,
properties.isFailOnCompositeError());
}
@Bean
@Primary
@ConditionalOnMissingBean(SearchPathLocator.class)
public CompositeEnvironmentRepository compositeEnvironmentRepository() {
return new CompositeEnvironmentRepository(this.environmentRepos);
return new CompositeEnvironmentRepository(this.environmentRepos,
properties.isFailOnCompositeError());
}
@Autowired
@@ -58,4 +62,9 @@ public class CompositeConfiguration {
this.environmentRepos = repos;
}
@Autowired
public void setProperties(ConfigServerProperties properties) {
this.properties = properties;
}
}

View File

@@ -73,6 +73,17 @@ public class ConfigServerProperties {
*/
private String defaultProfile = "default";
/**
* Flag indicating that if there are any errors reading properties from a subordinate
* environment repository in a composite environment repository, then the entire
* composite read should fail. Useful when set to false when a Vault repository is in
* the composite to allow clients to still read properties from other repositories
* without providing a valid Vault token.
*
* Defaults to true, resulting in a failure on any error.
*/
private boolean failOnCompositeError = true;
/**
* Decryption configuration for when server handles encrypted properties before
* sending them to clients.
@@ -147,6 +158,14 @@ public class ConfigServerProperties {
this.defaultProfile = defaultProfile;
}
public boolean isFailOnCompositeError() {
return failOnCompositeError;
}
public void setFailOnCompositeError(boolean failOnCompositeError) {
this.failOnCompositeError = failOnCompositeError;
}
/**
* Encryption properties.
*/

View File

@@ -429,16 +429,20 @@ class CompositeRepositoryConfiguration {
@Bean
@ConditionalOnSearchPathLocator
public SearchPathCompositeEnvironmentRepository searchPathCompositeEnvironmentRepository(
List<EnvironmentRepository> environmentRepositories) {
return new SearchPathCompositeEnvironmentRepository(environmentRepositories);
List<EnvironmentRepository> environmentRepositories,
ConfigServerProperties properties) {
return new SearchPathCompositeEnvironmentRepository(environmentRepositories,
properties.isFailOnCompositeError());
}
@Primary
@Bean
@ConditionalOnMissingSearchPathLocator
public CompositeEnvironmentRepository compositeEnvironmentRepository(
List<EnvironmentRepository> environmentRepositories) {
return new CompositeEnvironmentRepository(environmentRepositories);
List<EnvironmentRepository> environmentRepositories,
ConfigServerProperties properties) {
return new CompositeEnvironmentRepository(environmentRepositories,
properties.isFailOnCompositeError());
}
}

View File

@@ -19,6 +19,9 @@ package org.springframework.cloud.config.server.environment;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.core.OrderComparator;
@@ -30,17 +33,23 @@ import org.springframework.core.OrderComparator;
*/
public class CompositeEnvironmentRepository implements EnvironmentRepository {
Log log = LogFactory.getLog(getClass());
protected List<EnvironmentRepository> environmentRepositories;
private boolean failOnError;
/**
* Creates a new {@link CompositeEnvironmentRepository}.
* @param environmentRepositories The list of {@link EnvironmentRepository}s to create
* the composite from.
* @param failOnError whether to throw an exception if there is an error.
*/
public CompositeEnvironmentRepository(List<EnvironmentRepository> environmentRepositories) {
public CompositeEnvironmentRepository(List<EnvironmentRepository> environmentRepositories, boolean failOnError) {
// Sort the environment repositories by the priority
Collections.sort(environmentRepositories, OrderComparator.INSTANCE);
this.environmentRepositories = environmentRepositories;
this.failOnError = failOnError;
}
@Override
@@ -61,6 +70,15 @@ public class CompositeEnvironmentRepository implements EnvironmentRepository {
else {
for (EnvironmentRepository repo : environmentRepositories) {
env.addAll(repo.findOne(application, profile, label, includeOrigin).getPropertySources());
}
catch (Exception e) {
if (failOnError) {
throw e;
}
else {
log.info("Error adding environment for " + repo);
}
}
}
}
return env;

View File

@@ -40,6 +40,11 @@ public class JdbcEnvironmentProperties implements EnvironmentRepositoryPropertie
/** SQL used to query database for keys and values. */
private String sql = DEFAULT_SQL;
/**
* Flag to determine how to handle query exceptions.
*/
private boolean failOnError = true;
public boolean isEnabled() {
return enabled;
}
@@ -65,4 +70,12 @@ public class JdbcEnvironmentProperties implements EnvironmentRepositoryPropertie
this.sql = sql;
}
public boolean isFailOnError() {
return failOnError;
}
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
}

View File

@@ -27,6 +27,9 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.core.Ordered;
@@ -50,6 +53,8 @@ import org.springframework.util.StringUtils;
*/
public class JdbcEnvironmentRepository implements EnvironmentRepository, Ordered {
private static Log logger = LogFactory.getLog(JdbcEnvironmentRepository.class);
private final JdbcTemplate jdbc;
private final PropertiesResultSetExtractor extractor = new PropertiesResultSetExtractor();
@@ -58,10 +63,13 @@ public class JdbcEnvironmentRepository implements EnvironmentRepository, Ordered
private String sql;
private boolean failOnError;
public JdbcEnvironmentRepository(JdbcTemplate jdbc, JdbcEnvironmentProperties properties) {
this.jdbc = jdbc;
this.order = properties.getOrder();
this.sql = properties.getSql();
this.failOnError = properties.isFailOnError();
}
public String getSql() {
@@ -96,10 +104,24 @@ public class JdbcEnvironmentRepository implements EnvironmentRepository, Ordered
Collections.reverse(envs);
for (String app : applications) {
for (String env : envs) {
Map<String, String> next = (Map<String, String>) this.jdbc.query(this.sql,
new Object[] { app, env, label }, this.extractor);
if (!next.isEmpty()) {
environment.add(new PropertySource(app + "-" + env, next));
try {
Map<String, String> next = (Map<String, String>) this.jdbc.query(
this.sql, new Object[] { app, env, label }, this.extractor);
if (!next.isEmpty()) {
environment.add(new PropertySource(app + "-" + env, next));
}
}
catch (DataAccessException e) {
if (!failOnError) {
if (logger.isDebugEnabled()) {
logger.debug(
"Failed to retrieve configuration from JDBC Repository",
e);
}
}
else {
throw e;
}
}
}
}
@@ -115,6 +137,14 @@ public class JdbcEnvironmentRepository implements EnvironmentRepository, Ordered
this.order = order;
}
public boolean isFailOnError() {
return failOnError;
}
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
}
class PropertiesResultSetExtractor implements ResultSetExtractor<Map<String, String>> {

View File

@@ -32,9 +32,10 @@ public class SearchPathCompositeEnvironmentRepository extends CompositeEnvironme
* Creates a new {@link SearchPathCompositeEnvironmentRepository}.
* @param environmentRepositories The {@link EnvironmentRepository}s to create this
* composite from.
* @param failOnError whether to throw an exception if there is an error.
*/
public SearchPathCompositeEnvironmentRepository(List<EnvironmentRepository> environmentRepositories) {
super(environmentRepositories);
public SearchPathCompositeEnvironmentRepository(List<EnvironmentRepository> environmentRepositories, boolean failOnError) {
super(environmentRepositories, failOnError);
}
@Override

View File

@@ -76,7 +76,7 @@ public class CompositeEnvironmentRepositoryTests {
repos.add(new TestOrderedEnvironmentRepository(3, e1, loc1));
repos.add(new TestOrderedEnvironmentRepository(2, e3, loc2));
repos.add(new TestOrderedEnvironmentRepository(1, e2, loc3));
SearchPathCompositeEnvironmentRepository compositeRepo = new SearchPathCompositeEnvironmentRepository(repos);
SearchPathCompositeEnvironmentRepository compositeRepo = new SearchPathCompositeEnvironmentRepository(repos, true);
Environment compositeEnv = compositeRepo.findOne("foo", "bar", "world", false);
List<PropertySource> propertySources = compositeEnv.getPropertySources();
assertThat(propertySources.size()).isEqualTo(5);
@@ -121,16 +121,15 @@ public class CompositeEnvironmentRepositoryTests {
List<EnvironmentRepository> repos2 = new ArrayList<EnvironmentRepository>();
repos2.add(new TestOrderedEnvironmentRepository(3, e1, loc1));
repos2.add(new TestOrderedEnvironmentRepository(3, e2, loc2));
SearchPathCompositeEnvironmentRepository compositeRepo = new SearchPathCompositeEnvironmentRepository(repos);
SearchPathCompositeEnvironmentRepository compositeRepo = new SearchPathCompositeEnvironmentRepository(repos, true);
SearchPathCompositeEnvironmentRepository multiCompositeRepo = new SearchPathCompositeEnvironmentRepository(
repos2);
repos2, true);
Environment env = compositeRepo.findOne("app", "dev", "label", false);
assertThat(env.getVersion()).isEqualTo("1");
assertThat(env.getState()).isEqualTo("state");
Environment multiEnv = multiCompositeRepo.findOne("app", "dev", "label", false);
assertThat(multiEnv.getVersion()).isEqualTo(null);
assertThat(multiEnv.getState()).isEqualTo(null);
}
@Test
@@ -142,6 +141,38 @@ public class CompositeEnvironmentRepositoryTests {
}
}
@Test
public void testFailingSubordinateRepositorySkipped() {
PropertySource p1 = mock(PropertySource.class);
doReturn("p1").when(p1).getName();
PropertySource p2 = mock(PropertySource.class);
doReturn("p2").when(p2).getName();
String sLoc1 = "loc1";
String sLoc2 = "loc2";
Environment e1 = new Environment("app", "dev");
e1.add(p1);
e1.setVersion("1");
e1.setState("state");
Environment e2 = new Environment("app", "dev");
e2.add(p2);
e2.setVersion("2");
e2.setState("state2");
SearchPathLocator.Locations loc1 = new SearchPathLocator.Locations("app", "dev",
"label", "version", new String[] { sLoc1 });
SearchPathLocator.Locations loc2 = new SearchPathLocator.Locations("app", "dev",
"label", "version", new String[] { sLoc1, sLoc2 });
List<EnvironmentRepository> repos = new ArrayList<EnvironmentRepository>();
repos.add(new TestOrderedEnvironmentRepository(2, e1, loc1));
repos.add(new TestFailingEnvironmentRepository(1, e2, loc2));
SearchPathCompositeEnvironmentRepository compositeRepo = new SearchPathCompositeEnvironmentRepository(
repos, false);
Environment env = compositeRepo.findOne("app", "dev", "label", false);
List<PropertySource> propertySources = env.getPropertySources();
assertThat(propertySources.size()).isEqualTo(1);
assertThat(propertySources.get(0).getName()).isEqualTo("p1");
}
private static class TestOrderedEnvironmentRepository implements EnvironmentRepository, SearchPathLocator, Ordered {
private Environment env;
@@ -178,6 +209,27 @@ public class CompositeEnvironmentRepositoryTests {
}
private static class TestFailingEnvironmentRepository
extends TestOrderedEnvironmentRepository {
TestFailingEnvironmentRepository(int order, Environment env,
Locations locations) {
super(order, env, locations);
}
@Override
public Environment findOne(String application, String profile, String label,
boolean includeOrigin) {
throw new IllegalArgumentException("Failing for some reason");
}
@Override
public Environment findOne(String application, String profile, String label) {
throw new IllegalArgumentException("Failing for some reason");
}
}
@Configuration(proxyBeanMethods = false)
static class OverrideCompositeConfig {
@@ -185,7 +237,7 @@ public class CompositeEnvironmentRepositoryTests {
@Primary
CompositeEnvironmentRepository customCompositeEnvironmentRepository() {
return new CompositeEnvironmentRepository(Arrays.<EnvironmentRepository>asList(
new TestOrderedEnvironmentRepository(1, new Environment("app", "dev"), null)));
new TestOrderedEnvironmentRepository(1, new Environment("app", "dev"), null)), true);
}
}