Updated configuration to include the stubbing of the new load balancer; fixes gh-1391
This commit is contained in:
@@ -62,9 +62,6 @@ public class StubRunnerConfiguration {
|
||||
|
||||
private StubDownloaderBuilderProvider provider = new StubDownloaderBuilderProvider();
|
||||
|
||||
@Autowired
|
||||
private StubRunnerProperties props;
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@@ -77,9 +74,10 @@ public class StubRunnerConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public BatchStubRunner batchStubRunner(BeanFactory beanFactory) {
|
||||
StubRunnerOptionsBuilder builder = builder();
|
||||
if (this.props.getProxyHost() != null) {
|
||||
builder.withProxy(this.props.getProxyHost(), this.props.getProxyPort());
|
||||
StubRunnerProperties props = beanFactory.getBean(StubRunnerProperties.class);
|
||||
StubRunnerOptionsBuilder builder = builder(props);
|
||||
if (props.getProxyHost() != null) {
|
||||
builder.withProxy(props.getProxyHost(), props.getProxyPort());
|
||||
}
|
||||
StubRunnerOptions stubRunnerOptions = stubRunnerOptions(builder);
|
||||
BatchStubRunner batchStubRunner = new BatchStubRunnerFactory(stubRunnerOptions,
|
||||
@@ -101,30 +99,30 @@ public class StubRunnerConfiguration {
|
||||
};
|
||||
}
|
||||
|
||||
private StubRunnerOptionsBuilder builder() {
|
||||
private StubRunnerOptionsBuilder builder(StubRunnerProperties props) {
|
||||
return new StubRunnerOptionsBuilder()
|
||||
.withMinMaxPort(
|
||||
Integer.valueOf(resolvePlaceholder(this.props.getMinPort(),
|
||||
this.props.getMinPort())),
|
||||
Integer.valueOf(resolvePlaceholder(this.props.getMaxPort(),
|
||||
this.props.getMaxPort())))
|
||||
.withStubRepositoryRoot(this.props.getRepositoryRoot())
|
||||
.withStubsMode(resolvePlaceholder(this.props.getStubsMode()))
|
||||
.withStubsClassifier(resolvePlaceholder(this.props.getClassifier()))
|
||||
.withStubs(resolvePlaceholder(this.props.getIds()))
|
||||
.withUsername(resolvePlaceholder(this.props.getUsername()))
|
||||
.withPassword(resolvePlaceholder(this.props.getPassword()))
|
||||
.withStubPerConsumer(Boolean.parseBoolean(
|
||||
resolvePlaceholder(this.props.isStubsPerConsumer())))
|
||||
.withConsumerName(consumerName())
|
||||
Integer.valueOf(resolvePlaceholder(props.getMinPort(),
|
||||
props.getMinPort())),
|
||||
Integer.valueOf(resolvePlaceholder(props.getMaxPort(),
|
||||
props.getMaxPort())))
|
||||
.withStubRepositoryRoot(props.getRepositoryRoot())
|
||||
.withStubsMode(resolvePlaceholder(props.getStubsMode()))
|
||||
.withStubsClassifier(resolvePlaceholder(props.getClassifier()))
|
||||
.withStubs(resolvePlaceholder(props.getIds()))
|
||||
.withUsername(resolvePlaceholder(props.getUsername()))
|
||||
.withPassword(resolvePlaceholder(props.getPassword()))
|
||||
.withStubPerConsumer(Boolean
|
||||
.parseBoolean(resolvePlaceholder(props.isStubsPerConsumer())))
|
||||
.withConsumerName(consumerName(props))
|
||||
.withMappingsOutputFolder(
|
||||
resolvePlaceholder(this.props.getMappingsOutputFolder()))
|
||||
.withDeleteStubsAfterTest(Boolean.parseBoolean(
|
||||
resolvePlaceholder(this.props.isDeleteStubsAfterTest())))
|
||||
.withGenerateStubs(Boolean
|
||||
.parseBoolean(resolvePlaceholder(this.props.isGenerateStubs())))
|
||||
.withProperties(this.props.getProperties())
|
||||
.withHttpServerStubConfigurer(this.props.getHttpServerStubConfigurer());
|
||||
resolvePlaceholder(props.getMappingsOutputFolder()))
|
||||
.withDeleteStubsAfterTest(Boolean
|
||||
.parseBoolean(resolvePlaceholder(props.isDeleteStubsAfterTest())))
|
||||
.withGenerateStubs(
|
||||
Boolean.parseBoolean(resolvePlaceholder(props.isGenerateStubs())))
|
||||
.withProperties(props.getProperties())
|
||||
.withHttpServerStubConfigurer(props.getHttpServerStubConfigurer());
|
||||
}
|
||||
|
||||
private String[] resolvePlaceholder(String[] string) {
|
||||
@@ -142,9 +140,9 @@ public class StubRunnerConfiguration {
|
||||
return this.environment.resolvePlaceholders(string.toString());
|
||||
}
|
||||
|
||||
private String consumerName() {
|
||||
if (StringUtils.hasText(this.props.getConsumerName())) {
|
||||
return resolvePlaceholder(this.props.getConsumerName());
|
||||
private String consumerName(StubRunnerProperties props) {
|
||||
if (StringUtils.hasText(props.getConsumerName())) {
|
||||
return resolvePlaceholder(props.getConsumerName());
|
||||
}
|
||||
return this.environment.getProperty("spring.application.name");
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -44,12 +43,10 @@ import org.springframework.core.env.Environment;
|
||||
@ConditionalOnProperty(value = "stubrunner.cloud.enabled", matchIfMissing = true)
|
||||
public class StubRunnerSpringCloudAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
BeanFactory beanFactory;
|
||||
|
||||
@Bean
|
||||
public StubRunnerDiscoveryClientWrapper stubRunnerDiscoveryClientWrapper() {
|
||||
return new StubRunnerDiscoveryClientWrapper(this.beanFactory);
|
||||
public StubRunnerDiscoveryClientWrapper stubRunnerDiscoveryClientWrapper(
|
||||
BeanFactory beanFactory) {
|
||||
return new StubRunnerDiscoveryClientWrapper(beanFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -70,8 +67,6 @@ class StubRunnerDiscoveryClientWrapper implements BeanPostProcessor {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
DiscoveryClient discoveryClient;
|
||||
|
||||
StubFinder stubFinder;
|
||||
|
||||
StubMapperProperties stubMapperProperties;
|
||||
|
||||
@@ -18,11 +18,13 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
@@ -37,18 +39,21 @@ import org.springframework.cloud.contract.stubrunner.StubConfiguration;
|
||||
import org.springframework.cloud.contract.stubrunner.StubFinder;
|
||||
import org.springframework.cloud.contract.stubrunner.spring.cloud.ConditionalOnStubbedDiscoveryEnabled;
|
||||
import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties;
|
||||
import org.springframework.cloud.contract.stubrunner.spring.cloud.StubRunnerSpringCloudAutoConfiguration;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration;
|
||||
import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
|
||||
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides autoconfiguraion for the Spring Cloud Load Balancer module.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @since 2.2.3
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -57,15 +62,16 @@ import org.springframework.util.StringUtils;
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnBean(StubMapperProperties.class)
|
||||
@AutoConfigureBefore(LoadBalancerAutoConfiguration.class)
|
||||
@AutoConfigureAfter(LoadBalancerClientConfiguration.class)
|
||||
@AutoConfigureAfter({ LoadBalancerClientConfiguration.class,
|
||||
StubRunnerSpringCloudAutoConfiguration.class })
|
||||
@ConditionalOnStubbedDiscoveryEnabled
|
||||
public class SpringCloudLoadBalancerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
LoadBalancerClientFactory stubRunnerLoadBalancerClientFactory(StubFinder stubFinder,
|
||||
StubMapperProperties stubMapperProperties) {
|
||||
return new StubRunnerLoadBalancerClientFactory(stubFinder, stubMapperProperties);
|
||||
LoadBalancerClientFactory stubRunnerLoadBalancerClientFactory(
|
||||
BeanFactory beanFactory) {
|
||||
return new StubRunnerLoadBalancerClientFactory(beanFactory);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -73,20 +79,62 @@ public class SpringCloudLoadBalancerAutoConfiguration {
|
||||
class StubRunnerLoadBalancerClientFactory extends LoadBalancerClientFactory
|
||||
implements Closeable {
|
||||
|
||||
private final StubFinder stubFinder;
|
||||
private StubFinder stubFinder;
|
||||
|
||||
private final StubMapperProperties stubMapperProperties;
|
||||
private StubMapperProperties stubMapperProperties;
|
||||
|
||||
StubRunnerLoadBalancerClientFactory(StubFinder stubFinder,
|
||||
StubMapperProperties stubMapperProperties) {
|
||||
this.stubFinder = stubFinder;
|
||||
this.stubMapperProperties = stubMapperProperties;
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
StubRunnerLoadBalancerClientFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
private StubFinder stubFinder() {
|
||||
if (this.stubFinder == null) {
|
||||
this.stubFinder = this.beanFactory.getBean(StubFinder.class);
|
||||
}
|
||||
return this.stubFinder;
|
||||
}
|
||||
|
||||
private StubMapperProperties stubMapperProperties() {
|
||||
if (this.stubMapperProperties == null) {
|
||||
this.stubMapperProperties = this.beanFactory
|
||||
.getBean(StubMapperProperties.class);
|
||||
}
|
||||
return this.stubMapperProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId) {
|
||||
return request -> Mono.just(new DefaultResponse(
|
||||
new StubbedServiceInstance(stubFinder, stubMapperProperties, serviceId)));
|
||||
return (ReactorServiceInstanceLoadBalancer) request -> Mono
|
||||
.just(new DefaultResponse(new StubbedServiceInstance(stubFinder(),
|
||||
stubMapperProperties(), serviceId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getInstance(String name, Class<T> type) {
|
||||
return (T) getInstance(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getInstance(String name, Class<?> clazz, Class<?>... generics) {
|
||||
return (T) getInstance(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getInstance(String name, ResolvableType type) {
|
||||
return (T) getInstance(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Map<String, T> getInstances(String name, Class<T> type) {
|
||||
Map<String, T> map = new HashMap<>();
|
||||
map.put(name, (T) getInstance(name));
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner=\
|
||||
org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.spring.cloud.StubRunnerSpringCloudAutoConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer.SpringCloudLoadBalancerAutoConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.spring.cloud.ribbon.StubRunnerRibbonAutoConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.messaging.integration.StubRunnerIntegrationConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.messaging.jms.StubRunnerJmsConfiguration,\
|
||||
|
||||
@@ -28,12 +28,15 @@ import org.springframework.cloud.consul.ConsulAutoConfiguration
|
||||
import org.springframework.cloud.contract.stubrunner.StubFinder
|
||||
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner
|
||||
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties
|
||||
import org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer.StubRunnerLoadBalancerClientFactory
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration
|
||||
import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.test.context.TestPropertySource
|
||||
import org.springframework.web.client.RestTemplate
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
@@ -41,6 +44,7 @@ import org.springframework.web.client.RestTemplate
|
||||
//TODO: Document that ribbon.eureka.enabled=false needs to be set or override it somehow
|
||||
@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)
|
||||
@ActiveProfiles("cloudtest")
|
||||
@TestPropertySource(properties = "stubrunner.cloud.loadbalancer.enabled=false")
|
||||
// tag::autoconfigure[]
|
||||
@AutoConfigureStubRunner(
|
||||
ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance",
|
||||
@@ -56,6 +60,8 @@ class StubRunnerSpringCloudAutoConfigurationSpec extends Specification {
|
||||
@Autowired
|
||||
@LoadBalanced
|
||||
RestTemplate restTemplate
|
||||
@Autowired
|
||||
LoadBalancerClientFactory loadBalancerClientFactory;
|
||||
|
||||
@BeforeClass
|
||||
@AfterClass
|
||||
@@ -64,6 +70,10 @@ class StubRunnerSpringCloudAutoConfigurationSpec extends Specification {
|
||||
System.clearProperty("stubrunner.classifier")
|
||||
}
|
||||
|
||||
def setup() {
|
||||
assert !(loadBalancerClientFactory instanceof StubRunnerLoadBalancerClientFactory)
|
||||
}
|
||||
|
||||
// tag::test[]
|
||||
def 'should make service discovery work'() {
|
||||
expect: 'WireMocks are running'
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2013-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.contract.stubrunner.spring.cloud
|
||||
|
||||
import org.junit.AfterClass
|
||||
import org.junit.BeforeClass
|
||||
import spock.lang.Specification
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
import org.springframework.boot.test.context.SpringBootContextLoader
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced
|
||||
import org.springframework.cloud.consul.ConsulAutoConfiguration
|
||||
import org.springframework.cloud.contract.stubrunner.StubFinder
|
||||
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner
|
||||
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties
|
||||
import org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer.StubRunnerLoadBalancerClientFactory
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration
|
||||
import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.web.client.RestTemplate
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)
|
||||
@ActiveProfiles("cloudtest-no-ribbon")
|
||||
// tag::autoconfigure[]
|
||||
@AutoConfigureStubRunner(
|
||||
ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance",
|
||||
"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer",
|
||||
"org.springframework.cloud.contract.verifier.stubs:bootService"],
|
||||
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
|
||||
repositoryRoot = "classpath:m2repo/repository/")
|
||||
// end::autoconfigure[]
|
||||
class StubRunnerSpringCloudNoRibbonAutoConfigurationSpec extends Specification {
|
||||
|
||||
@Autowired
|
||||
StubFinder stubFinder
|
||||
@Autowired
|
||||
@LoadBalanced
|
||||
RestTemplate restTemplate
|
||||
@Autowired
|
||||
LoadBalancerClientFactory loadBalancerClientFactory;
|
||||
|
||||
@BeforeClass
|
||||
@AfterClass
|
||||
static void setupProps() {
|
||||
System.clearProperty("stubrunner.repository.root")
|
||||
System.clearProperty("stubrunner.classifier")
|
||||
}
|
||||
|
||||
def setup() {
|
||||
assert loadBalancerClientFactory instanceof StubRunnerLoadBalancerClientFactory
|
||||
}
|
||||
|
||||
// tag::test[]
|
||||
def 'should make service discovery work'() {
|
||||
expect: 'WireMocks are running'
|
||||
"${stubFinder.findStubUrl('loanIssuance').toString()}/name".toURL().text == 'loanIssuance'
|
||||
"${stubFinder.findStubUrl('fraudDetectionServer').toString()}/name".toURL().text == 'fraudDetectionServer'
|
||||
and: 'Stubs can be reached via load service discovery'
|
||||
restTemplate.getForObject('http://loanIssuance/name', String) == 'loanIssuance'
|
||||
restTemplate.getForObject('http://someNameThatShouldMapFraudDetectionServer/name', String) == 'fraudDetectionServer'
|
||||
}
|
||||
// end::test[]
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration(exclude = [EurekaClientAutoConfiguration,
|
||||
ConsulAutoConfiguration, ZookeeperAutoConfiguration])
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
@LoadBalanced
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
stubrunner:
|
||||
cloud.stubbed.discovery.enabled: true
|
||||
spring.cloud:
|
||||
zookeeper:
|
||||
enabled: false
|
||||
discovery.enabled: false
|
||||
consul:
|
||||
enabled: false
|
||||
discovery.enabled: false
|
||||
service-registry.enabled: false
|
||||
eureka.client.enabled: false
|
||||
ribbon.eureka.enabled: false
|
||||
spring:
|
||||
cloud:
|
||||
loadbalancer:
|
||||
ribbon:
|
||||
enabled: false # Use Reactive Load Balancer
|
||||
@@ -45,8 +45,10 @@ class JaxRsRequestMethodWhen implements When, JaxRsBodyParser {
|
||||
ContentType type = metadata.getInputTestContentType();
|
||||
String method = request.getMethod().getServerValue().toString().toLowerCase();
|
||||
if (request.getBody() != null) {
|
||||
String contentType = StringUtils.hasText(metadata.getDefinedInputTestContentType())
|
||||
? metadata.getDefinedInputTestContentType() : type.getMimeType();
|
||||
String contentType = StringUtils
|
||||
.hasText(metadata.getDefinedInputTestContentType())
|
||||
? metadata.getDefinedInputTestContentType()
|
||||
: type.getMimeType();
|
||||
Object body = request.getBody().getServerValue();
|
||||
String value;
|
||||
if (body instanceof ExecutionProperty) {
|
||||
|
||||
Reference in New Issue
Block a user