Adds support for config discovery in ConfigData.
ConsulConfigServerBootstrapper.java is registered in spring.factories The bootstrapper registers an ConfigServerInstanceProvider.Function that uses ConsulDiscoveryClient
This commit is contained in:
@@ -21,12 +21,12 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.context.config.ConfigDataLocationNotFoundException;
|
||||
@@ -82,12 +82,12 @@ public class ConsulConfigDataLocationResolver implements ConfigDataLocationResol
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConsulConfigDataLocation> resolveProfileSpecific(ConfigDataLocationResolverContext context,
|
||||
public List<ConsulConfigDataLocation> resolveProfileSpecific(ConfigDataLocationResolverContext resolverContext,
|
||||
String location, boolean optional, Profiles profiles) throws ConfigDataLocationNotFoundException {
|
||||
|
||||
UriComponents locationUri = parseLocation(context, location);
|
||||
UriComponents locationUri = parseLocation(resolverContext, location);
|
||||
|
||||
ConsulConfigProperties properties = loadConfigProperties(context.getBinder());
|
||||
ConsulConfigProperties properties = loadConfigProperties(resolverContext.getBinder());
|
||||
|
||||
ConsulPropertySources consulPropertySources = new ConsulPropertySources(properties, log);
|
||||
|
||||
@@ -95,13 +95,14 @@ public class ConsulConfigDataLocationResolver implements ConfigDataLocationResol
|
||||
? consulPropertySources.getAutomaticContexts(profiles.getAccepted())
|
||||
: getCustomContexts(locationUri, properties);
|
||||
|
||||
registerBean(context, ConsulProperties.class, loadProperties(context.getBinder(), locationUri));
|
||||
registerBean(resolverContext, ConsulProperties.class, loadProperties(resolverContext.getBinder(), locationUri));
|
||||
|
||||
registerAndPromoteBean(context, ConsulConfigProperties.class, () -> properties);
|
||||
registerAndPromoteBean(resolverContext, ConsulConfigProperties.class, InstanceSupplier.of(properties));
|
||||
|
||||
registerAndPromoteBean(context, ConsulClient.class, () -> createConsulClient(context));
|
||||
registerAndPromoteBean(resolverContext, ConsulClient.class, this::createConsulClient);
|
||||
|
||||
registerAndPromoteBean(context, ConsulConfigIndexes.class, ConsulConfigDataIndexes::new);
|
||||
registerAndPromoteBean(resolverContext, ConsulConfigIndexes.class,
|
||||
InstanceSupplier.from(ConsulConfigDataIndexes::new));
|
||||
|
||||
return contexts.stream().map(propertySourceContext -> new ConsulConfigDataLocation(propertySourceContext,
|
||||
optional, properties, consulPropertySources)).collect(Collectors.toList());
|
||||
@@ -144,12 +145,8 @@ public class ConsulConfigDataLocationResolver implements ConfigDataLocationResol
|
||||
return UriComponentsBuilder.fromUriString(uri).build();
|
||||
}
|
||||
|
||||
public <T> void registerBean(ConfigDataLocationResolverContext context, Class<T> type, T instance) {
|
||||
context.getBootstrapContext().registerIfAbsent(type, InstanceSupplier.of(instance));
|
||||
}
|
||||
|
||||
protected <T> void registerAndPromoteBean(ConfigDataLocationResolverContext context, Class<T> type,
|
||||
Supplier<T> supplier) {
|
||||
InstanceSupplier<T> supplier) {
|
||||
registerBean(context, type, supplier);
|
||||
context.getBootstrapContext().addCloseListener(event -> {
|
||||
T instance = event.getBootstrapContext().get(type);
|
||||
@@ -158,13 +155,18 @@ public class ConsulConfigDataLocationResolver implements ConfigDataLocationResol
|
||||
});
|
||||
}
|
||||
|
||||
protected <T> void registerBean(ConfigDataLocationResolverContext context, Class<T> type, Supplier<T> supplier) {
|
||||
ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext();
|
||||
bootstrapContext.registerIfAbsent(type, InstanceSupplier.from(supplier));
|
||||
public <T> void registerBean(ConfigDataLocationResolverContext context, Class<T> type, T instance) {
|
||||
context.getBootstrapContext().registerIfAbsent(type, InstanceSupplier.of(instance));
|
||||
}
|
||||
|
||||
protected ConsulClient createConsulClient(ConfigDataLocationResolverContext context) {
|
||||
ConsulProperties properties = context.getBootstrapContext().get(ConsulProperties.class);
|
||||
protected <T> void registerBean(ConfigDataLocationResolverContext context, Class<T> type,
|
||||
InstanceSupplier<T> supplier) {
|
||||
ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext();
|
||||
bootstrapContext.registerIfAbsent(type, supplier);
|
||||
}
|
||||
|
||||
protected ConsulClient createConsulClient(BootstrapContext context) {
|
||||
ConsulProperties properties = context.get(ConsulProperties.class);
|
||||
|
||||
return ConsulAutoConfiguration.createConsulClient(properties);
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ package org.springframework.cloud.consul.config;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
|
||||
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
|
||||
import org.springframework.boot.context.config.Profiles;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
@@ -93,18 +93,18 @@ public class ConsulConfigDataLocationResolverTests {
|
||||
return new ConsulConfigDataLocationResolver(LogFactory.getLog(getClass())) {
|
||||
@Override
|
||||
public <T> void registerBean(ConfigDataLocationResolverContext context, Class<T> type, T instance) {
|
||||
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> void registerBean(ConfigDataLocationResolverContext context, Class<T> type,
|
||||
Supplier<T> supplier) {
|
||||
|
||||
InstanceSupplier<T> supplier) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> void registerAndPromoteBean(ConfigDataLocationResolverContext context, Class<T> type,
|
||||
Supplier<T> supplier) {
|
||||
InstanceSupplier<T> supplier) {
|
||||
// do nothing
|
||||
}
|
||||
};
|
||||
|
||||
@@ -38,9 +38,14 @@ import org.springframework.core.style.ToStringCreator;
|
||||
* @author Venil Noronha
|
||||
* @author Richard Kettelerij
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.consul.discovery")
|
||||
@ConfigurationProperties(ConsulDiscoveryProperties.PREFIX)
|
||||
public class ConsulDiscoveryProperties {
|
||||
|
||||
/**
|
||||
* Consul discovery properties prefix.
|
||||
*/
|
||||
public static final String PREFIX = "spring.cloud.consul.discovery";
|
||||
|
||||
protected static final String MANAGEMENT = "management";
|
||||
|
||||
private HostInfo hostInfo;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2015-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.consul.discovery.configclient;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.Bootstrapper;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
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.ConfigServerInstanceProvider;
|
||||
import org.springframework.cloud.consul.ConsulAutoConfiguration;
|
||||
import org.springframework.cloud.consul.ConsulProperties;
|
||||
import org.springframework.cloud.consul.discovery.ConsulDiscoveryClient;
|
||||
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
|
||||
|
||||
public class ConsulConfigServerBootstrapper implements Bootstrapper {
|
||||
|
||||
@Override
|
||||
public void intitialize(BootstrapRegistry registry) {
|
||||
registry.registerIfAbsent(ConsulProperties.class, context -> {
|
||||
Binder binder = context.get(Binder.class);
|
||||
return binder.bind(ConsulProperties.PREFIX, ConsulProperties.class).orElseGet(ConsulProperties::new);
|
||||
});
|
||||
registry.registerIfAbsent(ConsulClient.class, context -> {
|
||||
ConsulProperties consulProperties = context.get(ConsulProperties.class);
|
||||
return ConsulAutoConfiguration.createConsulClient(consulProperties);
|
||||
});
|
||||
registry.registerIfAbsent(ConfigServerInstanceProvider.Function.class, context -> {
|
||||
Binder binder = context.get(Binder.class);
|
||||
boolean enabled = binder.bind(ConfigClientProperties.CONFIG_DISCOVERY_ENABLED, Boolean.class).orElse(false);
|
||||
if (!enabled) {
|
||||
return null;
|
||||
}
|
||||
ConsulClient consulClient = context.get(ConsulClient.class);
|
||||
ConsulDiscoveryProperties properties = binder
|
||||
.bind(ConsulDiscoveryProperties.PREFIX, ConsulDiscoveryProperties.class)
|
||||
.orElseGet(() -> new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties())));
|
||||
return new ConsulDiscoveryClient(consulClient, properties)::getInstances;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,9 @@ org.springframework.cloud.consul.discovery.ConsulDiscoveryClientConfiguration,\
|
||||
org.springframework.cloud.consul.discovery.reactive.ConsulReactiveDiscoveryClientConfiguration,\
|
||||
org.springframework.cloud.consul.discovery.ConsulCatalogWatchAutoConfiguration, \
|
||||
org.springframework.cloud.consul.support.ConsulHeartbeatAutoConfiguration
|
||||
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.consul.discovery.configclient.ConsulDiscoveryClientConfigServiceBootstrapConfiguration
|
||||
|
||||
org.springframework.boot.Bootstrapper=\
|
||||
org.springframework.cloud.consul.discovery.configclient.ConsulConfigServerBootstrapper
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2015-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.consul.discovery.configclient;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ConsulConfigServerBootstrapperTests {
|
||||
|
||||
@Test
|
||||
public void notEnabledDoesNotAddInstanceProviderFn() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapper(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
assertThat(providerFn).as("ConfigServerInstanceProvider.Function was created when it shouldn't")
|
||||
.isNull();
|
||||
})).run().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enabledDoesAddsInstanceProviderFn() {
|
||||
new SpringApplicationBuilder(TestConfig.class)
|
||||
.properties("spring.cloud.config.discovery.enabled=true",
|
||||
"spring.cloud.service-registry.auto-registration.enabled=false")
|
||||
.addBootstrapper(registry -> registry.addCloseListener(event -> {
|
||||
ConfigServerInstanceProvider.Function providerFn = event.getBootstrapContext()
|
||||
.get(ConfigServerInstanceProvider.Function.class);
|
||||
assertThat(providerFn).as("ConfigServerInstanceProvider.Function was not created when it should.")
|
||||
.isNotNull();
|
||||
})).run().close();
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user