diff --git a/spring-cloud-consul-config/src/main/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolver.java b/spring-cloud-consul-config/src/main/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolver.java index 93f16e05..520bd6b6 100644 --- a/spring-cloud-consul-config/src/main/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolver.java +++ b/spring-cloud-consul-config/src/main/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolver.java @@ -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 resolveProfileSpecific(ConfigDataLocationResolverContext context, + public List 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 void registerBean(ConfigDataLocationResolverContext context, Class type, T instance) { - context.getBootstrapContext().registerIfAbsent(type, InstanceSupplier.of(instance)); - } - protected void registerAndPromoteBean(ConfigDataLocationResolverContext context, Class type, - Supplier supplier) { + InstanceSupplier 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 void registerBean(ConfigDataLocationResolverContext context, Class type, Supplier supplier) { - ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext(); - bootstrapContext.registerIfAbsent(type, InstanceSupplier.from(supplier)); + public void registerBean(ConfigDataLocationResolverContext context, Class type, T instance) { + context.getBootstrapContext().registerIfAbsent(type, InstanceSupplier.of(instance)); } - protected ConsulClient createConsulClient(ConfigDataLocationResolverContext context) { - ConsulProperties properties = context.getBootstrapContext().get(ConsulProperties.class); + protected void registerBean(ConfigDataLocationResolverContext context, Class type, + InstanceSupplier supplier) { + ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext(); + bootstrapContext.registerIfAbsent(type, supplier); + } + + protected ConsulClient createConsulClient(BootstrapContext context) { + ConsulProperties properties = context.get(ConsulProperties.class); return ConsulAutoConfiguration.createConsulClient(properties); } diff --git a/spring-cloud-consul-config/src/test/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolverTests.java b/spring-cloud-consul-config/src/test/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolverTests.java index d1fb4f65..9cff992d 100644 --- a/spring-cloud-consul-config/src/test/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolverTests.java +++ b/spring-cloud-consul-config/src/test/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolverTests.java @@ -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 void registerBean(ConfigDataLocationResolverContext context, Class type, T instance) { - + // do nothing } @Override protected void registerBean(ConfigDataLocationResolverContext context, Class type, - Supplier supplier) { - + InstanceSupplier supplier) { + // do nothing } @Override protected void registerAndPromoteBean(ConfigDataLocationResolverContext context, Class type, - Supplier supplier) { + InstanceSupplier supplier) { // do nothing } }; diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java index 4f2abfe5..bdb3092c 100644 --- a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryProperties.java @@ -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; diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/configclient/ConsulConfigServerBootstrapper.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/configclient/ConsulConfigServerBootstrapper.java new file mode 100644 index 00000000..0d9bc477 --- /dev/null +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/configclient/ConsulConfigServerBootstrapper.java @@ -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; + }); + + } + +} diff --git a/spring-cloud-consul-discovery/src/main/resources/META-INF/spring.factories b/spring-cloud-consul-discovery/src/main/resources/META-INF/spring.factories index 935e9e7d..41abd4e8 100644 --- a/spring-cloud-consul-discovery/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-consul-discovery/src/main/resources/META-INF/spring.factories @@ -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 diff --git a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/configclient/ConsulConfigServerBootstrapperTests.java b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/configclient/ConsulConfigServerBootstrapperTests.java new file mode 100644 index 00000000..a17259a8 --- /dev/null +++ b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/configclient/ConsulConfigServerBootstrapperTests.java @@ -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 { + + } + +}