From eb0681f9c25c62c15b368674a2e0bf082663923c Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 29 Jan 2018 17:48:35 -0500 Subject: [PATCH] Get dynamic instanceinfo in ServiceRegistry.getStatus() See https://github.com/spring-cloud/spring-cloud-commons/issues/310 --- .../netflix/eureka/CloudEurekaClient.java | 13 +++- .../EurekaServiceRegistry.java | 18 +++-- .../EurekaServiceRegistryTests.java | 72 ++++++++++++++++++- 3 files changed, 96 insertions(+), 7 deletions(-) diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java index 04cd9ba4..d1c8ead7 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 the original author or authors. + * Copyright 2013-2018 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. @@ -24,6 +24,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.http.HttpStatus; import org.springframework.util.ReflectionUtils; import com.netflix.appinfo.ApplicationInfoManager; @@ -33,6 +34,7 @@ import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs; import com.netflix.discovery.DiscoveryClient; import com.netflix.discovery.EurekaClientConfig; import com.netflix.discovery.shared.transport.EurekaHttpClient; +import com.netflix.discovery.shared.transport.EurekaHttpResponse; /** * Subclass of {@link DiscoveryClient} that sends a {@link HeartbeatEvent} when @@ -73,6 +75,15 @@ public class CloudEurekaClient extends DiscoveryClient { getEurekaHttpClient().deleteStatusOverride(info.getAppName(), info.getId(), info); } + public InstanceInfo getInstanceInfo(String appname, String instanceId) { + EurekaHttpResponse response = getEurekaHttpClient().getInstance(appname, instanceId); + HttpStatus httpStatus = HttpStatus.valueOf(response.getStatusCode()); + if (httpStatus.is2xxSuccessful() && response.getEntity() != null) { + return response.getEntity(); + } + return null; + } + EurekaHttpClient getEurekaHttpClient() { if (this.eurekaHttpClient.get() == null) { try { diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistry.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistry.java index 2e28ca8d..47b4ddbb 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistry.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2016 the original author or authors. + * Copyright 2013-2018 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. @@ -25,6 +25,8 @@ import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import com.netflix.appinfo.InstanceInfo; +import static com.netflix.appinfo.InstanceInfo.InstanceStatus.UNKNOWN; + /** * @author Spencer Gibb */ @@ -89,11 +91,17 @@ public class EurekaServiceRegistry implements ServiceRegistry status = new HashMap<>(); + String appname = registration.getInstanceConfig().getAppname(); + String instanceId = registration.getInstanceConfig().getInstanceId(); + InstanceInfo info = registration.getEurekaClient().getInstanceInfo(appname, instanceId); - InstanceInfo info = registration.getApplicationInfoManager().getInfo(); - status.put("status", info.getStatus().toString()); - status.put("overriddenStatus", info.getOverriddenStatus().toString()); + HashMap status = new HashMap<>(); + if (info != null) { + status.put("status", info.getStatus().toString()); + status.put("overriddenStatus", info.getOverriddenStatus().toString()); + } else { + status.put("status", UNKNOWN.toString()); + } return status; } diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistryTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistryTests.java index 2ffe3189..eba2ce61 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistryTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaServiceRegistryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2017 the original author or authors. + * Copyright 2013-2018 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. @@ -17,6 +17,8 @@ package org.springframework.cloud.netflix.eureka.serviceregistry; +import java.util.Map; + import org.junit.Test; import org.springframework.cloud.commons.util.InetUtils; import org.springframework.cloud.commons.util.InetUtilsProperties; @@ -28,6 +30,9 @@ import org.springframework.context.ApplicationEventPublisher; import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.InstanceInfo; +import static com.netflix.appinfo.InstanceInfo.InstanceStatus.DOWN; +import static com.netflix.appinfo.InstanceInfo.InstanceStatus.UNKNOWN; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @@ -57,4 +62,69 @@ public class EurekaServiceRegistryTests { verifyZeroInteractions(eurekaClient); } + @Test + public void eurekaClientGetStatus() { + EurekaServiceRegistry registry = new EurekaServiceRegistry(); + + EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())); + config.setAppname("myapp"); + config.setInstanceId("1234"); + + CloudEurekaClient eurekaClient = mock(CloudEurekaClient.class); + + InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder() + .setAppName("myapp") + .setInstanceId("1234") + .setStatus(DOWN) + .setOverriddenStatus(UNKNOWN) + .build(); + when(eurekaClient.getInstanceInfo("myapp", "1234")) + .thenReturn(instanceInfo); + + EurekaRegistration registration = EurekaRegistration.builder(config) + .with(eurekaClient) + .with(mock(ApplicationInfoManager.class)) + .with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class)) + .build(); + + Object status = registry.getStatus(registration); + + assertThat(status).isInstanceOf(Map.class); + + Map map = (Map) status; + + assertThat(map).hasSize(2) + .containsEntry("status", DOWN.toString()) + .containsEntry("overriddenStatus", UNKNOWN.toString()); + } + + + @Test + public void eurekaClientGetStatusNoInstance() { + EurekaServiceRegistry registry = new EurekaServiceRegistry(); + + EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())); + config.setAppname("myapp"); + config.setInstanceId("1234"); + + CloudEurekaClient eurekaClient = mock(CloudEurekaClient.class); + + when(eurekaClient.getInstanceInfo("myapp", "1234")) + .thenReturn(null); + + EurekaRegistration registration = EurekaRegistration.builder(config) + .with(eurekaClient) + .with(mock(ApplicationInfoManager.class)) + .with(new EurekaClientConfigBean(), mock(ApplicationEventPublisher.class)) + .build(); + + Object status = registry.getStatus(registration); + + assertThat(status).isInstanceOf(Map.class); + + Map map = (Map) status; + + assertThat(map).hasSize(1) + .containsEntry("status", UNKNOWN.toString()); + } }