Daniel Lavoie
7 years ago
committed by
Spencer Gibb
17 changed files with 982 additions and 13 deletions
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.config; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; |
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy; |
||||
import org.springframework.cloud.netflix.eureka.MutableDiscoveryClientOptionalArgs; |
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
@Configuration |
||||
public class DiscoveryClientOptionalArgsConfiguration { |
||||
@Bean |
||||
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter") |
||||
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT) |
||||
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs() { |
||||
return new RestTemplateDiscoveryClientOptionalArgs(); |
||||
} |
||||
|
||||
@Bean |
||||
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter") |
||||
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT) |
||||
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() { |
||||
return new MutableDiscoveryClientOptionalArgs(); |
||||
} |
||||
} |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import java.util.List; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator; |
||||
import com.fasterxml.jackson.annotation.JsonProperty; |
||||
import com.netflix.discovery.shared.Application; |
||||
import com.netflix.discovery.shared.Applications; |
||||
|
||||
/** |
||||
* A simple wrapper class for {@link Applications} that insure proprer Jackson |
||||
* serialization through the JsonPropert overwrites. |
||||
* |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
public class EurekaApplications extends com.netflix.discovery.shared.Applications { |
||||
|
||||
@JsonCreator |
||||
public EurekaApplications(@JsonProperty("apps__hashcode") String appsHashCode, |
||||
@JsonProperty("versions__delta") Long versionDelta, |
||||
@JsonProperty("application") List<Application> registeredApplications) { |
||||
super(appsHashCode, versionDelta, registeredApplications); |
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
public class RestTemplateDiscoveryClientOptionalArgs |
||||
extends AbstractDiscoveryClientOptionalArgs<Void> { |
||||
public RestTemplateDiscoveryClientOptionalArgs() { |
||||
setTransportClientFactories(new RestTemplateTransportClientFactories()); |
||||
} |
||||
} |
@ -0,0 +1,227 @@
@@ -0,0 +1,227 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Map.Entry; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.http.HttpEntity; |
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.web.client.RestTemplate; |
||||
|
||||
import com.netflix.appinfo.InstanceInfo; |
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus; |
||||
import com.netflix.discovery.shared.Application; |
||||
import com.netflix.discovery.shared.Applications; |
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient; |
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse; |
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse.EurekaHttpResponseBuilder; |
||||
import com.netflix.discovery.util.StringUtil; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
public class RestTemplateEurekaHttpClient implements EurekaHttpClient { |
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
private RestTemplate restTemplate; |
||||
private String serviceUrl; |
||||
|
||||
public RestTemplateEurekaHttpClient(RestTemplate restTemplate, String serviceUrl) { |
||||
this.restTemplate = restTemplate; |
||||
this.serviceUrl = serviceUrl; |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Void> register(InstanceInfo info) { |
||||
String urlPath = serviceUrl + "apps/" + info.getAppName(); |
||||
|
||||
HttpHeaders headers = new HttpHeaders(); |
||||
headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip"); |
||||
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); |
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.POST, |
||||
new HttpEntity<InstanceInfo>(info, headers), Void.class); |
||||
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()) |
||||
.headers(headersOf(response)).build(); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Void> cancel(String appName, String id) { |
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id; |
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.DELETE, |
||||
null, Void.class); |
||||
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()) |
||||
.headers(headersOf(response)).build(); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id, |
||||
InstanceInfo info, InstanceStatus overriddenStatus) { |
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id + "?status=" |
||||
+ info.getStatus().toString() + "&lastDirtyTimestamp=" |
||||
+ info.getLastDirtyTimestamp().toString() + (overriddenStatus != null |
||||
? "&overriddenstatus=" + overriddenStatus.name() : ""); |
||||
|
||||
ResponseEntity<InstanceInfo> response = restTemplate.exchange(urlPath, |
||||
HttpMethod.PUT, null, InstanceInfo.class); |
||||
|
||||
EurekaHttpResponseBuilder<InstanceInfo> eurekaResponseBuilder = anEurekaHttpResponse( |
||||
response.getStatusCodeValue(), InstanceInfo.class) |
||||
.headers(headersOf(response)); |
||||
|
||||
if (response.hasBody()) |
||||
eurekaResponseBuilder.entity(response.getBody()); |
||||
|
||||
return eurekaResponseBuilder.build(); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Void> statusUpdate(String appName, String id, |
||||
InstanceStatus newStatus, InstanceInfo info) { |
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id + "?status=" |
||||
+ newStatus.name() + "&lastDirtyTimestamp=" |
||||
+ info.getLastDirtyTimestamp().toString(); |
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.PUT, |
||||
null, Void.class); |
||||
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()) |
||||
.headers(headersOf(response)).build(); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Void> deleteStatusOverride(String appName, String id, |
||||
InstanceInfo info) { |
||||
String urlPath = serviceUrl + "apps/" + appName + '/' + id |
||||
+ "/status?lastDirtyTimestamp=" + info.getLastDirtyTimestamp().toString(); |
||||
|
||||
ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.DELETE, |
||||
null, Void.class); |
||||
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue()) |
||||
.headers(headersOf(response)).build(); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Applications> getApplications(String... regions) { |
||||
return getApplicationsInternal("apps/", regions); |
||||
} |
||||
|
||||
private EurekaHttpResponse<Applications> getApplicationsInternal(String urlPath, |
||||
String[] regions) { |
||||
String url = serviceUrl + urlPath; |
||||
|
||||
if (regions != null && regions.length > 0) |
||||
urlPath = (urlPath.contains("?") ? "&" : "?") + "regions=" |
||||
+ StringUtil.join(regions); |
||||
|
||||
ResponseEntity<EurekaApplications> response = restTemplate.exchange(url, |
||||
HttpMethod.GET, null, EurekaApplications.class); |
||||
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue(), |
||||
response.getStatusCode().value() == HttpStatus.OK.value() |
||||
&& response.hasBody() ? (Applications) response.getBody() : null) |
||||
.headers(headersOf(response)).build(); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Applications> getDelta(String... regions) { |
||||
return getApplicationsInternal("apps/delta", regions); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Applications> getVip(String vipAddress, String... regions) { |
||||
return getApplicationsInternal("vips/" + vipAddress, regions); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Applications> getSecureVip(String secureVipAddress, |
||||
String... regions) { |
||||
return getApplicationsInternal("svips/" + secureVipAddress, regions); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<Application> getApplication(String appName) { |
||||
String urlPath = serviceUrl + "apps/" + appName; |
||||
|
||||
ResponseEntity<Application> response = restTemplate.exchange(urlPath, |
||||
HttpMethod.GET, null, Application.class); |
||||
|
||||
Application application = response.getStatusCodeValue() == HttpStatus.OK.value() |
||||
&& response.hasBody() ? response.getBody() : null; |
||||
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue(), application) |
||||
.headers(headersOf(response)).build(); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String appName, String id) { |
||||
return getInstanceInternal("apps/" + appName + '/' + id); |
||||
} |
||||
|
||||
@Override |
||||
public EurekaHttpResponse<InstanceInfo> getInstance(String id) { |
||||
return getInstanceInternal("instances/" + id); |
||||
} |
||||
|
||||
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String urlPath) { |
||||
urlPath = serviceUrl + urlPath; |
||||
|
||||
ResponseEntity<InstanceInfo> response = restTemplate.exchange(urlPath, |
||||
HttpMethod.GET, null, InstanceInfo.class); |
||||
|
||||
return anEurekaHttpResponse(response.getStatusCodeValue(), |
||||
response.getStatusCodeValue() == HttpStatus.OK.value() |
||||
&& response.hasBody() ? response.getBody() : null) |
||||
.headers(headersOf(response)).build(); |
||||
} |
||||
|
||||
@Override |
||||
public void shutdown() { |
||||
// Nothing to do
|
||||
} |
||||
|
||||
private static Map<String, String> headersOf(ResponseEntity<?> response) { |
||||
HttpHeaders httpHeaders = response.getHeaders(); |
||||
if (httpHeaders == null || httpHeaders.isEmpty()) { |
||||
return Collections.emptyMap(); |
||||
} |
||||
Map<String, String> headers = new HashMap<>(); |
||||
for (Entry<String, List<String>> entry : httpHeaders.entrySet()) { |
||||
if (!entry.getValue().isEmpty()) { |
||||
headers.put(entry.getKey(), entry.getValue().get(0)); |
||||
} |
||||
} |
||||
return headers; |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
import com.netflix.appinfo.InstanceInfo; |
||||
import com.netflix.discovery.EurekaClientConfig; |
||||
import com.netflix.discovery.shared.transport.TransportClientFactory; |
||||
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient; |
||||
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
public class RestTemplateTransportClientFactories |
||||
implements TransportClientFactories<Void> { |
||||
|
||||
@Override |
||||
public TransportClientFactory newTransportClientFactory( |
||||
Collection<Void> additionalFilters, EurekaJerseyClient providedJerseyClient) { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
|
||||
@Override |
||||
public TransportClientFactory newTransportClientFactory( |
||||
EurekaClientConfig clientConfig, Collection<Void> additionalFilters, |
||||
InstanceInfo myInstanceInfo) { |
||||
return new RestTemplateTransportClientFactory(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,98 @@
@@ -0,0 +1,98 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
|
||||
import org.springframework.http.client.support.BasicAuthorizationInterceptor; |
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; |
||||
import org.springframework.web.client.RestTemplate; |
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy; |
||||
import com.fasterxml.jackson.databind.SerializationFeature; |
||||
import com.netflix.discovery.shared.resolver.EurekaEndpoint; |
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient; |
||||
import com.netflix.discovery.shared.transport.TransportClientFactory; |
||||
|
||||
/** |
||||
* Provides the custom {@link RestTemplate} required by the |
||||
* {@link RestTemplateEurekaHttpClient}. Relies on Jackson for serialization and |
||||
* deserialization. |
||||
* |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
public class RestTemplateTransportClientFactory implements TransportClientFactory { |
||||
|
||||
@Override |
||||
public EurekaHttpClient newClient(EurekaEndpoint serviceUrl) { |
||||
return new RestTemplateEurekaHttpClient(restTemplate(serviceUrl.getServiceUrl()), |
||||
serviceUrl.getServiceUrl()); |
||||
} |
||||
|
||||
private RestTemplate restTemplate(String serviceUrl) { |
||||
RestTemplate restTemplate = new RestTemplate(); |
||||
try { |
||||
URI serviceURI = new URI(serviceUrl); |
||||
if (serviceURI.getUserInfo() != null) { |
||||
String[] credentials = serviceURI.getUserInfo().split(":"); |
||||
if (credentials.length == 2) { |
||||
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor( |
||||
credentials[0], credentials[1])); |
||||
} |
||||
} |
||||
} |
||||
catch (URISyntaxException ignore) { |
||||
|
||||
} |
||||
|
||||
restTemplate.getMessageConverters().add(0, mappingJacksonHttpMessageConverter()); |
||||
|
||||
return restTemplate; |
||||
} |
||||
|
||||
/** |
||||
* Provides the serialization configurations required by the Eureka Server. JSON |
||||
* content exchanged with eureka requires a root node matching the entity being |
||||
* serialized or deserialized. Achived with |
||||
* {@link SerializationFeature.WRAP_ROOT_VALUE} and |
||||
* {@link DeserializationFeature.UNWRAP_ROOT_VALUE}. |
||||
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying |
||||
* {@link ObjectMapper}. |
||||
* |
||||
* |
||||
* @return |
||||
*/ |
||||
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() { |
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); |
||||
converter.setObjectMapper(new ObjectMapper() |
||||
.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)); |
||||
|
||||
converter.getObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true); |
||||
converter.getObjectMapper().configure(DeserializationFeature.UNWRAP_ROOT_VALUE, |
||||
true); |
||||
|
||||
return converter; |
||||
} |
||||
|
||||
@Override |
||||
public void shutdown() { |
||||
} |
||||
|
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.config; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
||||
import org.springframework.cloud.netflix.eureka.sample.EurekaSampleApplication; |
||||
import org.springframework.test.annotation.DirtiesContext; |
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
||||
|
||||
import com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
@DirtiesContext |
||||
@RunWith(SpringJUnit4ClassRunner.class) |
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) |
||||
public class JerseyOptionalArgsConfigurationTest { |
||||
@Autowired |
||||
private DiscoveryClientOptionalArgs optionalArgs; |
||||
|
||||
@Test |
||||
public void contextLoads() { |
||||
Assert.assertNotNull(optionalArgs); |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.config; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.boot.builder.SpringApplicationBuilder; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
||||
import org.springframework.cloud.ClassPathExclusions; |
||||
import org.springframework.cloud.FilteredClassPathRunner; |
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs; |
||||
import org.springframework.cloud.netflix.eureka.sample.EurekaSampleApplication; |
||||
import org.springframework.context.ConfigurableApplicationContext; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
@RunWith(FilteredClassPathRunner.class) |
||||
@ClassPathExclusions({ "jersey-client-*", "jersey-core-*", "jersey-apache-client4-*" }) |
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) |
||||
public class RestTemplateOptionalArgsConfigurationTest { |
||||
@Test |
||||
public void contextLoads() { |
||||
try (ConfigurableApplicationContext context = new SpringApplicationBuilder() |
||||
.web(false).sources(EurekaSampleApplication.class).run()) { |
||||
Assert.assertNotNull( |
||||
context.getBean(RestTemplateDiscoveryClientOptionalArgs.class)); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,117 @@
@@ -0,0 +1,117 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; |
||||
import org.springframework.web.bind.annotation.DeleteMapping; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.PathVariable; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.PutMapping; |
||||
import org.springframework.web.bind.annotation.RequestBody; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.ResponseStatus; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import com.netflix.appinfo.InstanceInfo; |
||||
import com.netflix.discovery.shared.Application; |
||||
import com.netflix.discovery.shared.Applications; |
||||
|
||||
/** |
||||
* Mocked Eureka Server |
||||
* |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
@Configuration |
||||
@RestController |
||||
@SpringBootApplication |
||||
public class EurekaServerMockApplication { |
||||
private static final InstanceInfo INFO = new InstanceInfo(null, null, null, null, |
||||
null, null, null, null, null, null, null, null, null, 0, null, null, null, |
||||
null, null, null, null, 0l, 0l, null, null); |
||||
|
||||
/** |
||||
* Simulates Eureka Server own's serialization. |
||||
* @return |
||||
*/ |
||||
@Bean |
||||
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() { |
||||
return new RestTemplateTransportClientFactory() |
||||
.mappingJacksonHttpMessageConverter(); |
||||
} |
||||
|
||||
@ResponseStatus(HttpStatus.OK) |
||||
@PostMapping("/apps/{appName}") |
||||
public void register(@PathVariable String appName, |
||||
@RequestBody InstanceInfo instanceInfo) { |
||||
// Nothing to do
|
||||
} |
||||
|
||||
@ResponseStatus(HttpStatus.OK) |
||||
@DeleteMapping("/apps/{appName}/{id}") |
||||
public void cancel(@PathVariable String appName, @PathVariable String id) { |
||||
|
||||
} |
||||
|
||||
@ResponseStatus(HttpStatus.OK) |
||||
@PutMapping(value = "/apps/{appName}/{id}", params = { "status", |
||||
"lastDirtyTimestamp" }) |
||||
public InstanceInfo sendHeartBeat(@PathVariable String appName, |
||||
@PathVariable String id, @RequestParam String status, |
||||
@RequestParam String lastDirtyTimestamp, |
||||
@RequestParam(required = false) String overriddenstatus) { |
||||
return new InstanceInfo(null, null, null, null, null, null, null, null, null, |
||||
null, null, null, null, 0, null, null, null, null, null, null, null, 0l, |
||||
0l, null, null); |
||||
} |
||||
|
||||
@ResponseStatus(HttpStatus.OK) |
||||
@PutMapping(value = "/apps/{appName}/{id}/status", params = { "value", |
||||
"lastDirtyTimestamp" }) |
||||
public void statusUpdate(@PathVariable String appName, @PathVariable String id, |
||||
@RequestParam String value, @RequestParam String lastDirtyTimestamp) { |
||||
|
||||
} |
||||
|
||||
@ResponseStatus(HttpStatus.OK) |
||||
@DeleteMapping(value = "/apps/{appName}/{id}/status", params = "lastDirtyTimestamp") |
||||
public void deleteStatusOverride(@PathVariable String appName, |
||||
@PathVariable String id, @RequestParam String lastDirtyTimestamp) { |
||||
|
||||
} |
||||
|
||||
@GetMapping(value = { "/apps", "/apps/delta", "/vips/{address}", "/svips/{address}" }) |
||||
public Applications getApplications(@PathVariable(required = false) String address, |
||||
@RequestParam(required = false) String regions) { |
||||
return new Applications(); |
||||
} |
||||
|
||||
@GetMapping(value = "/apps/{appName}") |
||||
public Application getApplication(@PathVariable String appName) { |
||||
return new Application(); |
||||
} |
||||
|
||||
@GetMapping(value = { "/apps/{appName}/{id}", "/instances/{id}" }) |
||||
public InstanceInfo getInstance(@PathVariable(required = false) String appName, |
||||
@PathVariable String id) { |
||||
return INFO; |
||||
} |
||||
} |
@ -0,0 +1,139 @@
@@ -0,0 +1,139 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
||||
import org.springframework.cloud.commons.util.InetUtils; |
||||
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.test.annotation.DirtiesContext; |
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
||||
|
||||
import com.netflix.appinfo.InstanceInfo; |
||||
import com.netflix.appinfo.InstanceInfo.InstanceStatus; |
||||
import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider; |
||||
import com.netflix.discovery.shared.resolver.DefaultEndpoint; |
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
@RunWith(SpringJUnit4ClassRunner.class) |
||||
@SpringBootTest(classes = EurekaServerMockApplication.class, properties = { "debug=true", |
||||
"security.basic.enabled=true" }, webEnvironment = WebEnvironment.RANDOM_PORT) |
||||
@DirtiesContext |
||||
public class RestTemplateEurekaHttpClientTest { |
||||
@Autowired |
||||
private InetUtils inetUtils; |
||||
|
||||
@Value("http://${security.user.name}:${security.user.password}@localhost:${local.server.port}") |
||||
private String serviceUrl; |
||||
|
||||
private EurekaHttpClient eurekaHttpClient; |
||||
private InstanceInfo info; |
||||
|
||||
@Before |
||||
public void setup() { |
||||
eurekaHttpClient = new RestTemplateTransportClientFactory() |
||||
.newClient(new DefaultEndpoint(serviceUrl)); |
||||
|
||||
EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils); |
||||
|
||||
String appname = "customapp"; |
||||
config.setIpAddress("127.0.0.1"); |
||||
config.setHostname("localhost"); |
||||
config.setAppname(appname); |
||||
config.setVirtualHostName(appname); |
||||
config.setSecureVirtualHostName(appname); |
||||
config.setNonSecurePort(4444); |
||||
config.setInstanceId("127.0.0.1:customapp:4444"); |
||||
|
||||
info = new EurekaConfigBasedInstanceInfoProvider(config).get(); |
||||
} |
||||
|
||||
@Test |
||||
public void testRegister() { |
||||
Assert.assertEquals(HttpStatus.OK.value(), |
||||
eurekaHttpClient.register(info).getStatusCode()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCancel() { |
||||
Assert.assertEquals(HttpStatus.OK.value(), |
||||
eurekaHttpClient.cancel("test", "test").getStatusCode()); |
||||
} |
||||
|
||||
@Test |
||||
public void testSendHeartBeat() { |
||||
Assert.assertEquals(HttpStatus.OK.value(), eurekaHttpClient |
||||
.sendHeartBeat("test", "test", info, null).getStatusCode()); |
||||
} |
||||
|
||||
@Test |
||||
public void testStatusUpdate() { |
||||
Assert.assertEquals(HttpStatus.OK.value(), eurekaHttpClient |
||||
.statusUpdate("test", "test", InstanceStatus.UP, info).getStatusCode()); |
||||
} |
||||
|
||||
@Test |
||||
public void testDeleteStatusOverride() { |
||||
Assert.assertEquals(HttpStatus.OK.value(), eurekaHttpClient |
||||
.deleteStatusOverride("test", "test", info).getStatusCode()); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetApplications() { |
||||
Assert.assertNotNull(eurekaHttpClient.getApplications().getEntity()); |
||||
Assert.assertNotNull(eurekaHttpClient.getApplications("us", "eu").getEntity()); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetDelta() { |
||||
eurekaHttpClient.getDelta().getEntity(); |
||||
eurekaHttpClient.getDelta("us", "eu").getEntity(); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetVips() { |
||||
eurekaHttpClient.getVip("test"); |
||||
eurekaHttpClient.getVip("test", "us", "eu"); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetSecureVip() { |
||||
eurekaHttpClient.getSecureVip("test"); |
||||
eurekaHttpClient.getSecureVip("test", "us", "eu"); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetApplication() { |
||||
eurekaHttpClient.getApplication("test"); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetInstance() { |
||||
eurekaHttpClient.getInstance("test"); |
||||
eurekaHttpClient.getInstance("test", "test"); |
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
public class RestTemplateTransportClientFactoriesTest { |
||||
@Test(expected = UnsupportedOperationException.class) |
||||
public void testJerseyIsUnsuported() { |
||||
new RestTemplateTransportClientFactories().newTransportClientFactory(null, null); |
||||
} |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
/* |
||||
* Copyright 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.netflix.eureka.http; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
import com.netflix.discovery.shared.resolver.DefaultEndpoint; |
||||
|
||||
/** |
||||
* @author Daniel Lavoie |
||||
*/ |
||||
public class RestTemplateTransportClientFactoryTest { |
||||
private RestTemplateTransportClientFactory transportClientFatory; |
||||
|
||||
@Before |
||||
public void setup() { |
||||
transportClientFatory = new RestTemplateTransportClientFactory(); |
||||
} |
||||
|
||||
@Test |
||||
public void testWithoutUserInfo() { |
||||
transportClientFatory.newClient(new DefaultEndpoint("http://localhost:8761")); |
||||
} |
||||
|
||||
@Test |
||||
public void testInvalidUserInfo() { |
||||
transportClientFatory |
||||
.newClient(new DefaultEndpoint("http://test@localhost:8761")); |
||||
} |
||||
|
||||
@Test |
||||
public void testUserInfo() { |
||||
transportClientFatory |
||||
.newClient(new DefaultEndpoint("http://test:test@localhost:8761")); |
||||
} |
||||
|
||||
@After |
||||
public void shutdown() { |
||||
transportClientFatory.shutdown(); |
||||
} |
||||
} |
Loading…
Reference in new issue