diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClient.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClient.java index 73abc575..6d4e8dc7 100644 --- a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClient.java +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClient.java @@ -77,8 +77,16 @@ public class ConsulDiscoveryClient implements DiscoveryClient { String serviceId; Integer port; Map metadata; - if (service == null) { - // possibly called before registration + String host = "localhost"; + + // if we have a response from consul, that is the ultimate source of truth + if (service != null) { + serviceId = service.getId(); + port = service.getPort(); + host = service.getAddress(); + metadata = getMetadata(service.getTags()); + } else { + // possibly called before registration, use configuration or best guess log.warn("Unable to locate service in consul agent: " + lifecycle.getServiceId()); @@ -89,24 +97,32 @@ public class ConsulDiscoveryClient implements DiscoveryClient { port = serverProperties.getPort(); } metadata = getMetadata(this.properties.getTags()); + + if (StringUtils.hasText(this.properties.getHostname())) { + host = this.properties.getHostname(); + } else if (this.properties.isPreferAgentAddress()){ + // try and use the agent host + String agentHost = getAgentHost(); + if (agentHost != null) { + host = agentHost; + } + } } - else { - serviceId = service.getId(); - port = service.getPort(); - metadata = getMetadata(service.getTags()); - } - String host = "localhost"; + + return new DefaultServiceInstance(serviceId, host, port, false, metadata); + } + + private String getAgentHost() { Response agentSelf = client.getAgentSelf(); Member member = agentSelf.getValue().getMember(); if (member != null) { if (properties.isPreferIpAddress()) { - host = member.getAddress(); - } - else if (StringUtils.hasText(member.getName())) { - host = member.getName(); + return member.getAddress(); + } else if (StringUtils.hasText(member.getName())) { + return member.getName(); } } - return new DefaultServiceInstance(serviceId, host, port, false, metadata); + return null; } @Override diff --git a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientCustomizedTests.java b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientCustomizedTests.java index 61b3fec5..94b9a2bc 100644 --- a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientCustomizedTests.java +++ b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientCustomizedTests.java @@ -24,27 +24,29 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.consul.ConsulAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** * @author Spencer Gibb */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = ConsulDiscoveryClientCustomizedTests.MyTestConfig.class) -@WebIntegrationTest(value = { "spring.application.name=testConsulDiscovery2", +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ConsulDiscoveryClientCustomizedTests.MyTestConfig.class, + properties = { "spring.application.name=testConsulDiscovery2", "spring.cloud.consul.discovery.instanceId=testConsulDiscovery2Id", - "spring.cloud.consul.discovery.tags=plaintag,foo=bar,foo2=bar2=baz2" }, randomPort = true) + "spring.cloud.consul.discovery.hostname=testConsulDiscovery2Host", + "spring.cloud.consul.discovery.tags=plaintag,foo=bar,foo2=bar2=baz2" }, + webEnvironment = RANDOM_PORT) public class ConsulDiscoveryClientCustomizedTests { @Autowired diff --git a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientLocalServiceInstanceTests.java b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientLocalServiceInstanceTests.java new file mode 100644 index 00000000..58751c6c --- /dev/null +++ b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientLocalServiceInstanceTests.java @@ -0,0 +1,156 @@ +/* + * Copyright 2013-2016 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 + * + * http://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; + +import java.util.Arrays; +import java.util.Collections; + +import com.ecwid.consul.transport.RawResponse; +import com.ecwid.consul.v1.ConsulClient; +import com.ecwid.consul.v1.Response; +import com.ecwid.consul.v1.agent.model.Member; +import com.ecwid.consul.v1.agent.model.Self; +import com.ecwid.consul.v1.agent.model.Service; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.MOCK; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +/** + * @author Spencer Gibb + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = MOCK, + classes = ConsulDiscoveryClientLocalServiceInstanceTests.LocalServiceTestConfig.class, + properties = {"spring.cloud.consul.discovery.catalogServicesWatch.enabled=false"}) +public class ConsulDiscoveryClientLocalServiceInstanceTests { + + private static final String SERVICE_ID = "service1:8080"; + private static final String ADDRESS = "service1addr"; + private static final String SERVICE = "service1"; + private static final int PORT = 8080; + private static final String KEY = "foo"; + private static final String VALUE = "bar"; + private static final String TAG = KEY+"="+VALUE; + + @MockBean + private ConsulClient consul; + + @MockBean + private ConsulLifecycle lifecycle; + + @MockBean + private ConsulDiscoveryProperties properties; + + @Autowired + private ConsulDiscoveryClient discoveryClient; + public static final RawResponse RAW_RESPONSE = new RawResponse(200, null, null, 1L, false, null); + + @Test + public void localServiceInstanceFromConsul() { + Service service = new Service(); + service.setAddress(ADDRESS); + service.setService(SERVICE); + service.setPort(PORT); + service.setId(SERVICE_ID); + service.setTags(Arrays.asList(TAG)); + + given(this.lifecycle.getServiceId()).willReturn(SERVICE_ID); + + given(this.consul.getAgentServices()).willReturn(new Response<>(Collections.singletonMap(SERVICE_ID, service), RAW_RESPONSE)); + + ServiceInstance serviceInstance = this.discoveryClient.getLocalServiceInstance(); + + assertServiceInstance(serviceInstance); + } + + @Test + public void localServiceInstanceFromConfig() { + mockFromConfig(PORT, ADDRESS); + + ServiceInstance serviceInstance = this.discoveryClient.getLocalServiceInstance(); + + assertServiceInstance(serviceInstance); + } + + @Test + public void localServiceInstanceFromConfigPortFromServerProperties() { + mockFromConfig(0, ADDRESS); + + ServerProperties serverProperties = new ServerProperties(); + serverProperties.setPort(PORT); + this.discoveryClient.setServerProperties(serverProperties); + + ServiceInstance serviceInstance = this.discoveryClient.getLocalServiceInstance(); + + this.discoveryClient.setServerProperties(null); + + assertServiceInstance(serviceInstance); + } + + @Test + public void localServiceInstanceFromConfigHostFromAgent() { + mockFromConfig(PORT, null); + given(this.properties.isPreferAgentAddress()).willReturn(true); + Self self = new Self(); + Member member = new Member(); + member.setName(ADDRESS); + self.setMember(member); + given(this.consul.getAgentSelf()).willReturn(new Response<>(self, RAW_RESPONSE)); + + ServiceInstance serviceInstance = this.discoveryClient.getLocalServiceInstance(); + + assertServiceInstance(serviceInstance); + } + + private void assertServiceInstance(ServiceInstance serviceInstance) { + assertThat(serviceInstance.getHost()).isEqualTo(ADDRESS); + assertThat(serviceInstance.getPort()).isEqualTo(PORT); + assertThat(serviceInstance.getServiceId()).isEqualTo(SERVICE_ID); + assertThat(serviceInstance.getMetadata()).isNotEmpty().hasSize(1).contains(entry(KEY, VALUE)); + } + + private void mockFromConfig(int port, String address) { + given(this.lifecycle.getServiceId()).willReturn(SERVICE_ID); + given(this.lifecycle.getConfiguredPort()).willReturn(port); + given(this.properties.getTags()).willReturn(Arrays.asList(TAG)); + given(this.properties.getHostname()).willReturn(address); + + given(this.consul.getAgentServices()).willReturn(new Response<>(Collections.emptyMap(), RAW_RESPONSE)); + } + + @Configuration + @EnableDiscoveryClient + @EnableAutoConfiguration + @Import({ ConsulDiscoveryClientConfiguration.class }) + protected static class LocalServiceTestConfig { + + } +} diff --git a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientTests.java b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientTests.java index c4bb18c4..a081c0f0 100644 --- a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientTests.java +++ b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/discovery/ConsulDiscoveryClientTests.java @@ -22,14 +22,13 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.consul.ConsulAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.ecwid.consul.v1.ConsulClient; import com.ecwid.consul.v1.QueryParams; @@ -38,15 +37,17 @@ import com.ecwid.consul.v1.Response; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** * @author Spencer Gibb * @author Joe Athman */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = ConsulDiscoveryClientTests.MyTestConfig.class) -@WebIntegrationTest(value = { "spring.application.name=testConsulDiscovery", - "spring.cloud.consul.discovery.preferIpAddress=true" }, randomPort = true) +@RunWith(SpringRunner.class) +@SpringBootTest(properties = { "spring.application.name=testConsulDiscovery", + "spring.cloud.consul.discovery.preferIpAddress=true"}, + classes = ConsulDiscoveryClientTests.MyTestConfig.class, + webEnvironment = RANDOM_PORT) public class ConsulDiscoveryClientTests { @Autowired