Merge branch 'lomeshpatel-add-header-support-for-service-checks'

This commit is contained in:
Spencer Gibb
2018-09-17 16:18:34 -04:00
6 changed files with 128 additions and 13 deletions

View File

@@ -122,6 +122,34 @@ spring:
With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the `vcap.application.instance_id` will be populated automatically in a Spring Boot application, so the random value will not be needed.
==== Applying Headers to Health Check Requests
Headers can be applied to health check requests. For example, if you're trying to register a https://cloud.spring.io/spring-cloud-config/[Spring Cloud Config] server that uses https://github.com/spring-cloud/spring-cloud-config/blob/master/docs/src/main/asciidoc/spring-cloud-config.adoc#vault-backend[Vault Backend]:
.application.yml
----
spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token: 6442e58b-d1ea-182e-cfa5-cf9cddef0722
----
According to the HTTP standard, each header can have more than one values, in which case, an array can be supplied:
.application.yml
----
spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token:
- "6442e58b-d1ea-182e-cfa5-cf9cddef0722"
- "Some other value"
----
=== Looking up services
==== Using Ribbon

View File

@@ -14,7 +14,7 @@
<name>spring-cloud-consul-dependencies</name>
<description>Spring Cloud Consul Dependencies</description>
<properties>
<consul-api.version>1.3.1</consul-api.version>
<consul-api.version>1.4.1</consul-api.version>
</properties>
<dependencyManagement>
<dependencies>

View File

@@ -60,6 +60,9 @@ public class ConsulDiscoveryProperties {
/** Custom health check url to override default */
private String healthCheckUrl;
/** Headers to be applied to the Health Check calls */
private Map<String, List<String>> healthCheckHeaders = new HashMap<>();
/** How often to perform the health check (e.g. 10s), defaults to 10s. */
private String healthCheckInterval = "10s";
@@ -88,7 +91,7 @@ public class ConsulDiscoveryProperties {
/** Use ip address rather than hostname during registration */
private boolean preferIpAddress = false;
/** Source of how we will determine the address to use */
private boolean preferAgentAddress = false;
@@ -110,6 +113,7 @@ public class ConsulDiscoveryProperties {
/** Service instance group*/
private String instanceGroup;
/**
* Service instance zone comes from metadata.
* This allows changing the metadata tag name.
@@ -181,7 +185,7 @@ public class ConsulDiscoveryProperties {
/**
* @param serviceId The service who's filtering tag is being looked up
* @return The tag the given service id should be filtered by, or null.
*/
*/
public String getQueryTagForService(String serviceId){
String tag = serverListQueryTags.get(serviceId);
return tag != null ? tag : defaultQueryTag;
@@ -257,6 +261,14 @@ public class ConsulDiscoveryProperties {
this.healthCheckUrl = healthCheckUrl;
}
public Map<String, List<String>> getHealthCheckHeaders() {
return healthCheckHeaders;
}
public void setHealthCheckHeaders(Map<String, List<String>> healthCheckHeaders) {
this.healthCheckHeaders = healthCheckHeaders;
}
public String getHealthCheckInterval() {
return healthCheckInterval;
}
@@ -487,6 +499,7 @@ public class ConsulDiscoveryProperties {
", managementTags=" + managementTags +
", healthCheckPath='" + healthCheckPath + '\'' +
", healthCheckUrl='" + healthCheckUrl + '\'' +
", healthCheckHeaders='" + healthCheckHeaders + '\'' +
", healthCheckInterval='" + healthCheckInterval + '\'' +
", healthCheckTimeout='" + healthCheckTimeout + '\'' +
", healthCheckCriticalTimeout='" + healthCheckCriticalTimeout + '\'' +

View File

@@ -206,10 +206,10 @@ public class ConsulAutoRegistration extends ConsulRegistration {
if (!StringUtils.isEmpty(properties.getInstanceGroup())) {
tags.add("group=" + properties.getInstanceGroup());
}
//store the secure flag in the tags so that clients will be able to figure out whether to use http or https automatically
tags.add("secure=" + Boolean.toString(properties.getScheme().equalsIgnoreCase("https")));
return tags;
}
@@ -231,6 +231,7 @@ public class ConsulAutoRegistration extends ConsulRegistration {
properties.getHostname(), port,
properties.getHealthCheckPath()));
}
check.setHeader(properties.getHealthCheckHeaders());
check.setInterval(properties.getHealthCheckInterval());
check.setTimeout(properties.getHealthCheckTimeout());
if (StringUtils.hasText(properties.getHealthCheckCriticalTimeout())) {

View File

@@ -19,11 +19,11 @@ public class ConsulDiscoveryPropertiesTests {
private static final String SERVICE_NAME_IN_MAP = "serviceNameInMap";
private static final String SERVICE_NAME_NOT_IN_MAP = "serviceNameNotInMap";
private ConsulDiscoveryProperties properties;
private Map<String, String> serverListQueryTags = Collections.singletonMap(SERVICE_NAME_IN_MAP, MAP_TAG);
private Map<String, String> datacenters = Collections.singletonMap(SERVICE_NAME_IN_MAP, MAP_DC);
private final Map<String, String> serverListQueryTags = Collections.singletonMap(SERVICE_NAME_IN_MAP, MAP_TAG);
private final Map<String, String> datacenters = Collections.singletonMap(SERVICE_NAME_IN_MAP, MAP_DC);
@Before
public void setUp() throws Exception {
public void setUp() {
properties = new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties()));
properties.setDefaultQueryTag(DEFAULT_TAG);
properties.setServerListQueryTags(serverListQueryTags);
@@ -31,29 +31,29 @@ public class ConsulDiscoveryPropertiesTests {
}
@Test
public void testReturnsNullWhenNoDefaultAndNotInMap() throws Exception {
public void testReturnsNullWhenNoDefaultAndNotInMap() {
properties.setDefaultQueryTag(null);
assertNull(properties.getQueryTagForService(SERVICE_NAME_NOT_IN_MAP));
}
@Test
public void testGetTagReturnsDefaultWhenNotInMap() throws Exception {
public void testGetTagReturnsDefaultWhenNotInMap() {
assertEquals(DEFAULT_TAG, properties.getQueryTagForService(SERVICE_NAME_NOT_IN_MAP));
}
@Test
public void testGetTagReturnsMapValueWhenInMap() throws Exception {
public void testGetTagReturnsMapValueWhenInMap() {
assertEquals(MAP_TAG, properties.getQueryTagForService(SERVICE_NAME_IN_MAP));
}
@Test
public void testGetDcReturnsNullWhenNotInMap() throws Exception {
public void testGetDcReturnsNullWhenNotInMap() {
assertNull(properties.getDatacenters().get(SERVICE_NAME_NOT_IN_MAP));
}
@Test
public void testGetDcReturnsMapValueWhenInMap() throws Exception {
public void testGetDcReturnsMapValueWhenInMap() {
assertEquals(MAP_DC, properties.getDatacenters().get(SERVICE_NAME_IN_MAP));
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2013-2017 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.serviceregistry;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
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.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.consul.ConsulAutoConfiguration;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import com.ecwid.consul.v1.agent.model.NewService;
/**
* @author Lomesh Patel
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConsulAutoRegistrationHealthCheckHeadersTests.TestConfig.class, properties = {
"spring.application.name=myTestService-DiscoveryHealthCheckTlsSkipVerify",
"spring.cloud.consul.discovery.health-check-headers.X-Config-Token=ACCESSTOKEN" }, webEnvironment = RANDOM_PORT)
public class ConsulAutoRegistrationHealthCheckHeadersTests {
@Autowired
private ConsulAutoRegistration registration;
@Autowired
private ConsulDiscoveryProperties properties;
@Test
public void contextLoads() {
NewService service = this.registration.getService();
assertThat(service).as("service was null").isNotNull();
NewService.Check check = service.getCheck();
assertThat(check).as("check was null").isNotNull();
assertThat(check.getHeader()).as("header is null").isNotNull();
assertThat(check.getHeader()).as("header is empty").isNotEmpty();
assertThat(check.getHeader().get("X-Config-Token").get(0))
.as("expected header value not found").isEqualTo("ACCESSTOKEN");
// unable to call consul api to get health check details
}
@Configuration
@EnableAutoConfiguration
@ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class,
ConsulAutoConfiguration.class,
ConsulAutoServiceRegistrationAutoConfiguration.class })
public static class TestConfig {
}
}