Pass binder to ConfigServerInstanceProvider

This commit is contained in:
Ryan Baxter
2023-05-21 19:18:17 -04:00
parent 6effa362ff
commit 4e7f929a46
3 changed files with 63 additions and 19 deletions

View File

@@ -210,7 +210,8 @@ public class ConfigServerConfigDataLocationResolver
if (ConfigClientRetryBootstrapper.RETRY_IS_PRESENT && retryEnabled) {
log.debug(LogMessage.format("discovery plus retry enabled"));
RetryTemplate retryTemplate = RetryTemplateFactory.create(propertyHolder.retryProperties, log);
instanceProvider = new ConfigServerInstanceProvider(function) {
instanceProvider = new ConfigServerInstanceProvider(function, resolverContext.getBinder(),
getBindHandler(resolverContext)) {
@Override
public List<ServiceInstance> getConfigServerInstances(String serviceId) {
return retryTemplate.execute(retryContext -> super.getConfigServerInstances(serviceId));
@@ -218,7 +219,8 @@ public class ConfigServerConfigDataLocationResolver
};
}
else {
instanceProvider = new ConfigServerInstanceProvider(function);
instanceProvider = new ConfigServerInstanceProvider(function, resolverContext.getBinder(),
getBindHandler(resolverContext));
}
instanceProvider.setLog(log);

View File

@@ -21,6 +21,8 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.retry.annotation.Retryable;
@@ -36,6 +38,10 @@ public class ConfigServerInstanceProvider {
private final Function function;
private BindHandler bindHandler;
private Binder binder;
@Deprecated
public ConfigServerInstanceProvider(DiscoveryClient client) {
this.function = client::getInstances;
@@ -45,6 +51,12 @@ public class ConfigServerInstanceProvider {
this.function = function;
}
public ConfigServerInstanceProvider(Function function, Binder binder, BindHandler bindHandler) {
this.function = function;
this.binder = binder;
this.bindHandler = bindHandler;
}
void setLog(Log log) {
this.log = log;
}
@@ -54,7 +66,13 @@ public class ConfigServerInstanceProvider {
if (log.isDebugEnabled()) {
log.debug("Locating configserver (" + serviceId + ") via discovery");
}
List<ServiceInstance> instances = this.function.apply(serviceId);
List<ServiceInstance> instances;
if (binder == null || bindHandler == null) {
instances = this.function.apply(serviceId);
}
else {
instances = this.function.apply(serviceId, binder, bindHandler, log);
}
if (instances.isEmpty()) {
throw new IllegalStateException("No instances found of configserver (" + serviceId + ")");
}
@@ -70,6 +88,10 @@ public class ConfigServerInstanceProvider {
List<ServiceInstance> apply(String serviceId);
default List<ServiceInstance> apply(String serviceId, Binder binder, BindHandler bindHandler, Log log) {
return apply(serviceId);
};
}
}

View File

@@ -21,16 +21,18 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.BootstrapRegistryInitializer;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
@@ -41,8 +43,14 @@ import org.springframework.context.ConfigurableApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.config.client.ConfigClientProperties.Discovery.DEFAULT_CONFIG_SERVER;
/**
@@ -54,7 +62,7 @@ public class DiscoveryClientConfigDataConfigurationNoRetryTests {
protected ConfigurableApplicationContext context;
protected DiscoveryClient client = Mockito.mock(DiscoveryClient.class);
protected DiscoveryClient client = mock(DiscoveryClient.class);
protected ServiceInstance info = new DefaultServiceInstance("app:8877", "app", "foo", 8877, false);
@@ -68,43 +76,54 @@ public class DiscoveryClientConfigDataConfigurationNoRetryTests {
@Test
public void shouldFailWithExceptionGetConfigServerInstanceFromDiscoveryClient() throws Exception {
givenDiscoveryClientReturnsNoInfo();
assertThatThrownBy(() -> context = setup("spring.cloud.config.discovery.enabled=true",
ConfigServerInstanceProvider.Function function = mock(ConfigServerInstanceProvider.Function.class);
when(function.apply(anyString(), any(Binder.class), any(BindHandler.class), any(Log.class)))
.thenAnswer(invocation -> client.getInstances(invocation.getArgument(0)));
assertThatThrownBy(() -> context = setup(true, function, "spring.cloud.config.discovery.enabled=true",
"spring.cloud.config.fail-fast=true").run()).isInstanceOf(IllegalStateException.class)
.hasMessageContaining("No instances found of configserver");
verify(function).apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class));
verify(function, never()).apply(eq(DEFAULT_CONFIG_SERVER));
}
@Test
public void shouldFailWithMessageGetConfigServerInstanceFromDiscoveryClient() throws Exception {
givenDiscoveryClientReturnsNoInfo();
context = setup("spring.cloud.config.discovery.enabled=true", "spring.cloud.config.fail-fast=false").run();
ConfigServerInstanceProvider.Function function = mock(ConfigServerInstanceProvider.Function.class);
when(function.apply(anyString(), any(Binder.class), any(BindHandler.class), any(Log.class)))
.thenAnswer(invocation -> client.getInstances(invocation.getArgument(0)));
context = setup(true, function, "spring.cloud.config.discovery.enabled=true",
"spring.cloud.config.fail-fast=false").run();
// expectDiscoveryClientConfigServiceBootstrapConfigurationIsSetup();
expectConfigClientPropertiesHasDefaultConfiguration();
verifyDiscoveryClientCalledOnce();
verify(function).apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class));
verify(function, never()).apply(eq(DEFAULT_CONFIG_SERVER));
}
@Test
public void shouldSucceedGetConfigServerInstanceFromDiscoveryClient() throws Exception {
givenDiscoveryClientReturnsInfo();
context = setup("spring.cloud.config.discovery.enabled=true", "spring.cloud.config.fail-fast=true").run();
ConfigServerInstanceProvider.Function function = mock(ConfigServerInstanceProvider.Function.class);
when(function.apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class)))
.thenAnswer(invocation -> client.getInstances(invocation.getArgument(0)));
context = setup(true, function, "spring.cloud.config.discovery.enabled=true",
"spring.cloud.config.fail-fast=true").run();
// expectDiscoveryClientConfigServiceBootstrapConfigurationIsSetup();
// expectConfigClientPropertiesHasConfigurationFromEureka();
verifyDiscoveryClientCalledOnce();
verify(function).apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class));
verify(function, never()).apply(eq(DEFAULT_CONFIG_SERVER));
}
SpringApplicationBuilder setup(String... env) {
return setup(true, env);
}
SpringApplicationBuilder setup(boolean addInstanceProvider, String... env) {
SpringApplicationBuilder setup(boolean addInstanceProvider, ConfigServerInstanceProvider.Function function,
String... env) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(TestConfig.class)
.properties(addDefaultEnv(env));
if (addInstanceProvider) {
builder.addBootstrapRegistryInitializer(instanceProviderBootstrapper());
builder.addBootstrapRegistryInitializer(instanceProviderBootstrapper(function));
// ignore actual calls to config server since we're just testing discovery
// client.
builder.addBootstrapRegistryInitializer(registry -> registry
@@ -116,9 +135,10 @@ public class DiscoveryClientConfigDataConfigurationNoRetryTests {
}));
}
protected BootstrapRegistryInitializer instanceProviderBootstrapper() {
protected BootstrapRegistryInitializer instanceProviderBootstrapper(
ConfigServerInstanceProvider.Function function) {
return registry -> registry.register(ConfigServerInstanceProvider.Function.class,
BootstrapRegistry.InstanceSupplier.from(() -> this.client::getInstances));
BootstrapRegistry.InstanceSupplier.from(() -> function));
}
private String[] addDefaultEnv(String[] env) {