Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove ConsulFunction and Use PropertyResolver #833

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,18 @@
package org.springframework.cloud.consul.discovery.configclient;

import java.util.Collections;
import java.util.List;

import com.ecwid.consul.v1.ConsulClient;
import org.apache.commons.logging.Log;

import org.springframework.boot.BootstrapContext;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.BootstrapRegistryInitializer;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.cloud.config.client.ConfigClientProperties;
import org.springframework.cloud.config.client.ConfigServerConfigDataLocationResolver;
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
import org.springframework.cloud.consul.ConsulAutoConfiguration;
import org.springframework.cloud.consul.ConsulProperties;
Expand All @@ -51,36 +48,35 @@ public void initialize(BootstrapRegistry registry) {
}
// create consul client
registry.registerIfAbsent(ConsulProperties.class, context -> {
Binder binder = context.get(Binder.class);
if (!isDiscoveryEnabled(binder)) {
if (!isDiscoveryEnabled(context)) {
return null;
}
return binder.bind(ConsulProperties.PREFIX, Bindable.of(ConsulProperties.class), getBindHandler(context))
.orElseGet(ConsulProperties::new);
ConfigServerConfigDataLocationResolver.PropertyResolver propertyResolver = getPropertyResolver(context);
return propertyResolver.resolveConfigurationProperties(ConsulProperties.PREFIX, ConsulProperties.class,
ConsulProperties::new);
});
registry.registerIfAbsent(ConsulClient.class, context -> {
if (!isDiscoveryEnabled(context.get(Binder.class))) {
if (!isDiscoveryEnabled(context)) {
return null;
}
ConsulProperties consulProperties = context.get(ConsulProperties.class);
return ConsulAutoConfiguration.createConsulClient(consulProperties,
ConsulAutoConfiguration.createConsulRawClientBuilder());
});
registry.registerIfAbsent(ConsulDiscoveryClient.class, context -> {
Binder binder = context.get(Binder.class);
if (!isDiscoveryEnabled(binder)) {
if (!isDiscoveryEnabled(context)) {
return null;
}
ConfigServerConfigDataLocationResolver.PropertyResolver propertyResolver = getPropertyResolver(context);
ConsulClient consulClient = context.get(ConsulClient.class);
ConsulDiscoveryProperties properties = binder
.bind(ConsulDiscoveryProperties.PREFIX, Bindable.of(ConsulDiscoveryProperties.class),
getBindHandler(context))
.orElseGet(() -> new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties())));
ConsulDiscoveryProperties properties = propertyResolver.resolveConfigurationProperties(
ConsulDiscoveryProperties.PREFIX, ConsulDiscoveryProperties.class,
() -> new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties())));
return new ConsulDiscoveryClient(consulClient, properties);
});
// promote discovery client if created
registry.addCloseListener(event -> {
if (!isDiscoveryEnabled(event.getBootstrapContext().get(Binder.class))) {
if (!isDiscoveryEnabled(event.getBootstrapContext())) {
return;
}
ConsulDiscoveryClient discoveryClient = event.getBootstrapContext().get(ConsulDiscoveryClient.class);
Expand All @@ -90,71 +86,28 @@ public void initialize(BootstrapRegistry registry) {
}
});

// We need to pass the lambda here so we do not create a new instance of
// ConfigServerInstanceProvider.Function
// which would result in a ClassNotFoundException when Spring Cloud Config is not
// on the classpath
registry.registerIfAbsent(ConfigServerInstanceProvider.Function.class, ConsulFunction::create);
}

private BindHandler getBindHandler(org.springframework.boot.BootstrapContext context) {
return context.getOrElse(BindHandler.class, null);
registry.registerIfAbsent(ConfigServerInstanceProvider.Function.class, context -> {
if (!isDiscoveryEnabled(context)) {
return (id) -> Collections.emptyList();
}
ConsulDiscoveryClient discoveryClient = context.get(ConsulDiscoveryClient.class);
return discoveryClient::getInstances;
});
}

private static boolean isDiscoveryEnabled(Binder binder) {
return binder.bind(ConfigClientProperties.CONFIG_DISCOVERY_ENABLED, Boolean.class).orElse(false)
&& binder.bind(ConditionalOnConsulDiscoveryEnabled.PROPERTY, Boolean.class).orElse(true)
&& binder.bind("spring.cloud.discovery.enabled", Boolean.class).orElse(true);
private static ConfigServerConfigDataLocationResolver.PropertyResolver getPropertyResolver(
BootstrapContext context) {
return context.getOrElseSupply(ConfigServerConfigDataLocationResolver.PropertyResolver.class,
() -> new ConfigServerConfigDataLocationResolver.PropertyResolver(context.get(Binder.class),
context.getOrElse(BindHandler.class, null)));
}

/*
* This Function is executed when loading config data. Because of this we cannot rely
* on the BootstrapContext because Boot has not finished loading all the configuration
* data so if we ask the BootstrapContext for configuration data it will not have it.
* The apply method in this function is passed the Binder and BindHandler from the
* config data context which has the configuration properties that have been loaded so
* far in the config data process.
*
* We will create many of the same beans in this function as we do above in the
* initializer above. We do both to maintain compatibility since we are promoting
* those beans to the main application context.
*/
static final class ConsulFunction implements ConfigServerInstanceProvider.Function {

private final BootstrapContext context;

private ConsulFunction(BootstrapContext context) {
this.context = context;
}

public static ConsulFunction create(BootstrapContext context) {
return new ConsulFunction(context);
}

@Override
public List<ServiceInstance> apply(String serviceId) {
return apply(serviceId, null, null, null);
}

@Override
public List<ServiceInstance> apply(String serviceId, Binder binder, BindHandler bindHandler, Log log) {
if (binder == null || !isDiscoveryEnabled(binder)) {
return Collections.emptyList();
}

ConsulProperties consulProperties = binder
.bind(ConsulProperties.PREFIX, Bindable.of(ConsulProperties.class), bindHandler)
.orElseGet(ConsulProperties::new);
ConsulClient consulClient = ConsulAutoConfiguration.createConsulClient(consulProperties,
ConsulAutoConfiguration.createConsulRawClientBuilder());
ConsulDiscoveryProperties properties = binder
.bind(ConsulDiscoveryProperties.PREFIX, Bindable.of(ConsulDiscoveryProperties.class), bindHandler)
.orElseGet(() -> new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties())));
ConsulDiscoveryClient discoveryClient = new ConsulDiscoveryClient(consulClient, properties);

return discoveryClient.getInstances(serviceId);
}

public static boolean isDiscoveryEnabled(BootstrapContext bootstrapContext) {
ConfigServerConfigDataLocationResolver.PropertyResolver propertyResolver = getPropertyResolver(
bootstrapContext);
return propertyResolver.get(ConfigClientProperties.CONFIG_DISCOVERY_ENABLED, Boolean.class, false)
&& propertyResolver.get(ConditionalOnConsulDiscoveryEnabled.PROPERTY, Boolean.class, true)
&& propertyResolver.get("spring.cloud.discovery.enabled", Boolean.class, true);
}

}