Commit 69f85687 by Johannes Edmeier

Discover applications on ApplicationReadyEvent

Since there is no Heartbeat or InstanceRegisteredEvent when using the SimpleDiscoveryClient we need to listen on the ApplicationReadyEvent and register the configured instances closes #505
parent 7c3130b4
...@@ -44,7 +44,7 @@ See also the https://github.com/codecentric/spring-boot-admin/tree/master/spring ...@@ -44,7 +44,7 @@ See also the https://github.com/codecentric/spring-boot-admin/tree/master/spring
[[register-client-applications]] [[register-client-applications]]
=== Registering client applications === === Registering client applications ===
To register your application at the SBA Server you can either include the SBA Client or use http://projects.spring.io/spring-cloud/spring-cloud.html[Spring Cloud Discovery] (e.g. Eureka) To register your application at the SBA Server you can either include the SBA Client or use http://projects.spring.io/spring-cloud/spring-cloud.html[Spring Cloud Discovery] (e.g. Eureka, Consul, ...). There is also a <<spring-cloud-discovery-static-config,simple option using a static configuration on the SBA Server side>>.
[[register-clients-via-spring-boot-admin]] [[register-clients-via-spring-boot-admin]]
==== spring-boot-admin-starter-client ==== ==== spring-boot-admin-starter-client ====
......
[[spring-cloud-discovery-support]] [[spring-cloud-discovery-support]]
=== Spring Cloud Discovery === === Spring Cloud Discovery ===
The Spring Boot Admin Server can use Spring Clouds `DiscoveryClient` to discover applications. The advantage is that the clients don't have to include the `spring-boot-admin-starter-client`. You just have to add a DiscoveryClient to your admin server - everything else is done by AutoConfiguration. The Spring Boot Admin Server can use Spring Clouds `DiscoveryClient` to discover applications. The advantage is that the clients don't have to include the `spring-boot-admin-starter-client`. You just have to add a `DiscoveryClient` implementation to your admin server - everything else is done by AutoConfiguration.
The setup is explained <<discover-clients-via-spring-cloud-discovery,above>>.
[[spring-cloud-discovery-static-config]]
==== ServiceInstanceConverter ==== ==== SimpleDiscoveryClient configuration ====
Spring Boot Admin ships with the `SimpleDiscoveryClient` included. This allows you to specify client applications via configuration, without adding the SBA Client or a DiscoveryClient implementation to your monitored applications:
[source,yml]
.application.yml
----
spring:
cloud:
discovery:
client:
simple:
instances:
test:
- uri: http://instance1.intern:8080
metadata:
management.context-path: /actuator
- uri: http://instance2.intern:8080
metadata:
management.context-path: /actuator
----
==== Other DiscoveryClient implementations (Eureka, Zookeeper, Consul, ...) ====
Spring Boot Admin supports all other implementation of Spring Cloud's `DiscoveryClient`. You need to add it to the Spring Boot Admin Server and configure it properly.
An <<discover-clients-via-spring-cloud-discovery,example setup using Eureka>> is shown above.
==== Converting ServiceInstances into monitored applications ====
The information from the service registry are converted by the `ServiceInstanceConverter`. Spring Boot Admin ships with a default and Eureka converter implementation. The correct one is selected by AutoConfiguration. The information from the service registry are converted by the `ServiceInstanceConverter`. Spring Boot Admin ships with a default and Eureka converter implementation. The correct one is selected by AutoConfiguration.
...@@ -12,6 +38,28 @@ TIP: You can modify how the information from the registry is used to register th ...@@ -12,6 +38,28 @@ TIP: You can modify how the information from the registry is used to register th
NOTE: When using Eureka, the `healthCheckUrl` known to Eureka is used for health-checking, which can be set on your client using `eureka.instance.healthCheckUrl`. NOTE: When using Eureka, the `healthCheckUrl` known to Eureka is used for health-checking, which can be set on your client using `eureka.instance.healthCheckUrl`.
.Instance metadata options
|===
| Key |Value |Default value
| user.name +
user.password
| Credentials being used to access the endpoints.
|
| management.port
| The port is substituted in the service URL and will be used for accessing the actuator endpoints.
|
| management.context-path
| The path is appended to the service URL and will be used for accessing the actuator endpoints.
| `${spring.boot.admin.discovery.converter.mangement-context-path}`
| health.path
| The path is appended to the service URL and will be used for the health-checking. Ignored by the `EurekaServiceInstanceConverter`.
| `${spring.boot.admin.discovery.converter.health-endpoint}`
|===
.Discovery configuration options .Discovery configuration options
|=== |===
| Property name |Description |Default value | Property name |Description |Default value
...@@ -36,25 +84,3 @@ NOTE: When using Eureka, the `healthCheckUrl` known to Eureka is used for health ...@@ -36,25 +84,3 @@ NOTE: When using Eureka, the `healthCheckUrl` known to Eureka is used for health
| This services will be included when using discovery and registered as application. Supports simple patterns (e.g. "foo*", "*bar", "foo*bar*"). | This services will be included when using discovery and registered as application. Supports simple patterns (e.g. "foo*", "*bar", "foo*bar*").
| `"*"` | `"*"`
|=== |===
.Instance metadata options
|===
| Key |Value |Default value
| user.name +
user.password
| Credentials being used to access the endpoints.
|
| management.port
| The port is substituted in the service URL and will be used for accessing the actuator endpoints.
|
| management.context-path
| The path is appended to the service URL and will be used for accessing the actuator endpoints.
| `${spring.boot.admin.discovery.converter.mangement-context-path}`
| health.path
| The path is appended to the service URL and will be used for the health-checking. Ignored by the `EurekaServiceInstanceConverter`.
| `${spring.boot.admin.discovery.converter.health-endpoint}`
|===
/* /*
* Copyright 2014 the original author or authors. * Copyright 2014-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
...@@ -15,12 +15,15 @@ ...@@ -15,12 +15,15 @@
*/ */
package de.codecentric.boot.admin.discovery; package de.codecentric.boot.admin.discovery;
import de.codecentric.boot.admin.model.Application;
import de.codecentric.boot.admin.registry.ApplicationRegistry;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.Collections;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
...@@ -30,142 +33,142 @@ import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent; ...@@ -30,142 +33,142 @@ import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.util.PatternMatchUtils; import org.springframework.util.PatternMatchUtils;
import de.codecentric.boot.admin.model.Application;
import de.codecentric.boot.admin.registry.ApplicationRegistry;
/** /**
* Listener for Heartbeats events to publish all services to the application registry. * Listener for Heartbeats events to publish all services to the application registry.
* *
* @author Johannes Edmeier * @author Johannes Edmeier
*/ */
public class ApplicationDiscoveryListener { public class ApplicationDiscoveryListener {
private static final Logger LOGGER = LoggerFactory private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationDiscoveryListener.class);
.getLogger(ApplicationDiscoveryListener.class); private static final String SOURCE = "discovery";
private static final String SOURCE = "discovery"; private final DiscoveryClient discoveryClient;
private final DiscoveryClient discoveryClient; private final ApplicationRegistry registry;
private final ApplicationRegistry registry; private final HeartbeatMonitor monitor = new HeartbeatMonitor();
private final HeartbeatMonitor monitor = new HeartbeatMonitor(); private ServiceInstanceConverter converter = new DefaultServiceInstanceConverter();
private ServiceInstanceConverter converter = new DefaultServiceInstanceConverter();
/**
/** * Set of serviceIds to be ignored and not to be registered as application. Supports simple
* Set of serviceIds to be ignored and not to be registered as application. Supports simple * patterns (e.g. "foo*", "*foo", "foo*bar").
* patterns (e.g. "foo*", "*foo", "foo*bar"). */
*/ private Set<String> ignoredServices = new HashSet<>();
private Set<String> ignoredServices = new HashSet<>();
/**
/** * Set of serviceIds that has to match to be registered as application. Supports simple
* Set of serviceIds that has to match to be registered as application. Supports simple * patterns (e.g. "foo*", "*foo", "foo*bar"). Default value is everything
* patterns (e.g. "foo*", "*foo", "foo*bar"). Default value is everything */
*/ private Set<String> services = new HashSet<>(Collections.singletonList("*"));
private Set<String> services = new HashSet<>(Collections.singletonList("*"));
public ApplicationDiscoveryListener(DiscoveryClient discoveryClient, ApplicationRegistry registry) {
public ApplicationDiscoveryListener(DiscoveryClient discoveryClient, this.discoveryClient = discoveryClient;
ApplicationRegistry registry) { this.registry = registry;
this.discoveryClient = discoveryClient; }
this.registry = registry;
} @EventListener
public void onInstanceRegistered(InstanceRegisteredEvent<?> event) {
@EventListener discover();
public void onInstanceRegistered(InstanceRegisteredEvent<?> event) { }
discover();
} @EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
@EventListener discover();
public void onParentHeartbeat(ParentHeartbeatEvent event) { }
discoverIfNeeded(event.getValue());
} @EventListener
public void onParentHeartbeat(ParentHeartbeatEvent event) {
@EventListener discoverIfNeeded(event.getValue());
public void onApplicationEvent(HeartbeatEvent event) { }
discoverIfNeeded(event.getValue());
} @EventListener
public void onHeartbeat(HeartbeatEvent event) {
private void discoverIfNeeded(Object value) { discoverIfNeeded(event.getValue());
if (this.monitor.update(value)) { }
discover();
} private void discoverIfNeeded(Object value) {
} if (this.monitor.update(value)) {
discover();
protected void discover() { }
final Set<String> staleApplicationIds = getAllApplicationIdsFromRegistry(); }
for (String serviceId : discoveryClient.getServices()) {
if (!ignoreService(serviceId) && registerService(serviceId)) { protected void discover() {
for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) { final Set<String> staleApplicationIds = getAllApplicationIdsFromRegistry();
String applicationId = register(instance); for (String serviceId : discoveryClient.getServices()) {
staleApplicationIds.remove(applicationId); if (!ignoreService(serviceId) && registerService(serviceId)) {
} for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
} else { String applicationId = register(instance);
LOGGER.debug("Ignoring discovered service {}", serviceId); staleApplicationIds.remove(applicationId);
} }
} } else {
for (String staleApplicationId : staleApplicationIds) { LOGGER.debug("Ignoring discovered service {}", serviceId);
LOGGER.info("Application ({}) missing in DiscoveryClient services ", }
staleApplicationId); }
registry.deregister(staleApplicationId); for (String staleApplicationId : staleApplicationIds) {
} LOGGER.info("Application ({}) missing in DiscoveryClient services ", staleApplicationId);
} registry.deregister(staleApplicationId);
}
protected boolean ignoreService(final String serviceId) { }
return checkPatternIsMatching(serviceId, ignoredServices);
} protected boolean ignoreService(final String serviceId) {
return checkPatternIsMatching(serviceId, ignoredServices);
protected boolean registerService(final String serviceId) { }
return checkPatternIsMatching(serviceId, services);
} protected boolean registerService(final String serviceId) {
return checkPatternIsMatching(serviceId, services);
protected boolean checkPatternIsMatching(String serviceId, Set<String> patterns) { }
for (String pattern : patterns) {
if(PatternMatchUtils.simpleMatch(pattern, serviceId)) { protected boolean checkPatternIsMatching(String serviceId, Set<String> patterns) {
return true; for (String pattern : patterns) {
} if (PatternMatchUtils.simpleMatch(pattern, serviceId)) {
} return true;
return false; }
} }
return false;
protected final Set<String> getAllApplicationIdsFromRegistry() { }
Set<String> result = new HashSet<>();
for (Application application : registry.getApplications()) { protected final Set<String> getAllApplicationIdsFromRegistry() {
if (!ignoreService(application.getName()) && registerService(application.getName()) Set<String> result = new HashSet<>();
&& SOURCE.equals(application.getSource())) { for (Application application : registry.getApplications()) {
result.add(application.getId()); if (!ignoreService(application.getName()) &&
} registerService(application.getName()) &&
} SOURCE.equals(application.getSource())) {
return result; result.add(application.getId());
} }
}
protected String register(ServiceInstance instance) { return result;
try { }
Application application = converter.convert(instance);
application = Application.copyOf(application).withSource(SOURCE).build(); protected String register(ServiceInstance instance) {
if (application != null) { try {
LOGGER.debug("Registering discovered application {}", application); Application application = converter.convert(instance);
return registry.register(application).getId(); application = Application.copyOf(application).withSource(SOURCE).build();
} else { if (application != null) {
LOGGER.warn("No application for service {} registered", instance); LOGGER.debug("Registering discovered application {}", application);
} return registry.register(application).getId();
} catch (Exception ex) { } else {
LOGGER.error("Couldn't register application for service {}", instance, ex); LOGGER.warn("No application for service {} registered", instance);
} }
return null; } catch (Exception ex) {
} LOGGER.error("Couldn't register application for service {}", instance, ex);
}
public void setConverter(ServiceInstanceConverter converter) { return null;
this.converter = converter; }
}
public void setConverter(ServiceInstanceConverter converter) {
public void setIgnoredServices(Set<String> ignoredServices) { this.converter = converter;
this.ignoredServices = ignoredServices; }
}
public void setIgnoredServices(Set<String> ignoredServices) {
public Set<String> getIgnoredServices() { this.ignoredServices = ignoredServices;
return ignoredServices; }
}
public Set<String> getIgnoredServices() {
public Set<String> getServices() { return ignoredServices;
return services; }
}
public Set<String> getServices() {
public void setServices(Set<String> services) { return services;
this.services = services; }
}
public void setServices(Set<String> services) {
this.services = services;
}
} }
/* /*
* Copyright 2014 the original author or authors. * Copyright 2014-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
...@@ -15,174 +15,185 @@ ...@@ -15,174 +15,185 @@
*/ */
package de.codecentric.boot.admin.discovery; package de.codecentric.boot.admin.discovery;
import static java.util.Arrays.asList; import de.codecentric.boot.admin.model.Application;
import static java.util.Collections.singleton; import de.codecentric.boot.admin.registry.ApplicationRegistry;
import static org.junit.Assert.assertEquals; import de.codecentric.boot.admin.registry.HashingApplicationUrlIdGenerator;
import static org.mockito.Mockito.mock; import de.codecentric.boot.admin.registry.store.SimpleApplicationStore;
import static org.mockito.Mockito.when;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent; import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import de.codecentric.boot.admin.model.Application; import static java.util.Arrays.asList;
import de.codecentric.boot.admin.registry.ApplicationRegistry; import static java.util.Collections.singleton;
import de.codecentric.boot.admin.registry.HashingApplicationUrlIdGenerator; import static org.junit.Assert.assertEquals;
import de.codecentric.boot.admin.registry.store.SimpleApplicationStore; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ApplicationDiscoveryListenerTest { public class ApplicationDiscoveryListenerTest {
private ApplicationDiscoveryListener listener; private ApplicationDiscoveryListener listener;
private DiscoveryClient discovery; private DiscoveryClient discovery;
private ApplicationRegistry registry; private ApplicationRegistry registry;
@Before @Before
public void setup() { public void setup() {
registry = new ApplicationRegistry(new SimpleApplicationStore(), registry = new ApplicationRegistry(new SimpleApplicationStore(), new HashingApplicationUrlIdGenerator());
new HashingApplicationUrlIdGenerator()); registry.setApplicationEventPublisher(mock(ApplicationEventPublisher.class));
registry.setApplicationEventPublisher(mock(ApplicationEventPublisher.class)); discovery = mock(DiscoveryClient.class);
discovery = mock(DiscoveryClient.class); listener = new ApplicationDiscoveryListener(discovery, registry);
listener = new ApplicationDiscoveryListener(discovery, registry); }
}
@Test
@Test public void test_ignore() {
public void test_ignore() { when(discovery.getServices()).thenReturn(Collections.singletonList("service"));
when(discovery.getServices()).thenReturn(Collections.singletonList("service")); when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
when(discovery.getInstances("service")).thenReturn(Collections.singletonList( (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
(ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
listener.setIgnoredServices(singleton("service"));
listener.setIgnoredServices(singleton("service")); listener.onInstanceRegistered(null);
listener.onInstanceRegistered(new InstanceRegisteredEvent<>(new Object(), null));
assertEquals(0, registry.getApplications().size());
assertEquals(0, registry.getApplications().size()); }
}
@Test
@Test public void test_application_ready() {
public void test_matching() { when(discovery.getServices()).thenReturn(Collections.singletonList("service"));
when(discovery.getServices()).thenReturn(Collections.singletonList("service")); when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
when(discovery.getInstances("service")).thenReturn(Collections.singletonList( (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
(ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
listener.setServices(singleton("notService"));
listener.setServices(singleton("notService")); listener.onApplicationReady(null);
listener.onInstanceRegistered(new InstanceRegisteredEvent<>(new Object(), null));
assertEquals(0, registry.getApplications().size());
assertEquals(0, registry.getApplications().size()); }
}
@Test
@Test public void test_matching() {
public void test_ignore_pattern() { when(discovery.getServices()).thenReturn(Collections.singletonList("service"));
when(discovery.getServices()).thenReturn(asList("service", "rabbit-1", "rabbit-2")); when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
when(discovery.getInstances("service")).thenReturn(Collections.singletonList( (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
(ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
listener.setServices(singleton("notService"));
listener.setIgnoredServices(singleton("rabbit-*")); listener.onInstanceRegistered(null);
listener.onInstanceRegistered(new InstanceRegisteredEvent<>(new Object(), null));
assertEquals(0, registry.getApplications().size());
Collection<Application> applications = registry.getApplications(); }
assertEquals(1, applications.size());
assertEquals("service", applications.iterator().next().getName()); @Test
} public void test_ignore_pattern() {
when(discovery.getServices()).thenReturn(asList("service", "rabbit-1", "rabbit-2"));
@Test when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
public void test_matching_pattern() { (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
when(discovery.getServices()).thenReturn(asList("service", "rabbit-1", "rabbit-2"));
when(discovery.getInstances("service")).thenReturn(Collections.singletonList( listener.setIgnoredServices(singleton("rabbit-*"));
(ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false))); listener.onInstanceRegistered(null);
listener.setServices(singleton("ser*")); Collection<Application> applications = registry.getApplications();
listener.onInstanceRegistered(new InstanceRegisteredEvent<>(new Object(), null)); assertEquals(1, applications.size());
assertEquals("service", applications.iterator().next().getName());
Collection<Application> applications = registry.getApplications(); }
assertEquals(1, applications.size());
assertEquals("service", applications.iterator().next().getName()); @Test
} public void test_matching_pattern() {
when(discovery.getServices()).thenReturn(asList("service", "rabbit-1", "rabbit-2"));
@Test when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
public void test_matching_and_ignore_pattern() { (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
when(discovery.getServices()).thenReturn(asList("service-1", "service", "rabbit-1", "rabbit-2"));
when(discovery.getInstances("service")).thenReturn(Collections.singletonList( listener.setServices(singleton("ser*"));
(ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false))); listener.onInstanceRegistered(null);
when(discovery.getInstances("service-1")).thenReturn(Collections.singletonList(
(ServiceInstance) new DefaultServiceInstance("service-1", "localhost", 80, false))); Collection<Application> applications = registry.getApplications();
assertEquals(1, applications.size());
listener.setServices(singleton("ser*")); assertEquals("service", applications.iterator().next().getName());
listener.setIgnoredServices(singleton("service-*")); }
listener.onInstanceRegistered(new InstanceRegisteredEvent<>(new Object(), null));
@Test
Collection<Application> applications = registry.getApplications(); public void test_matching_and_ignore_pattern() {
assertEquals(1, applications.size()); when(discovery.getServices()).thenReturn(asList("service-1", "service", "rabbit-1", "rabbit-2"));
assertEquals("service", applications.iterator().next().getName()); when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
} (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
when(discovery.getInstances("service-1")).thenReturn(Collections.singletonList(
@Test (ServiceInstance) new DefaultServiceInstance("service-1", "localhost", 80, false)));
public void test_register_and_convert() {
when(discovery.getServices()).thenReturn(Collections.singletonList("service")); listener.setServices(singleton("ser*"));
when(discovery.getInstances("service")).thenReturn(Collections.singletonList( listener.setIgnoredServices(singleton("service-*"));
(ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false))); listener.onInstanceRegistered(null);
listener.onInstanceRegistered(new InstanceRegisteredEvent<>(new Object(), null)); Collection<Application> applications = registry.getApplications();
assertEquals(1, applications.size());
assertEquals(1, registry.getApplications().size()); assertEquals("service", applications.iterator().next().getName());
Application application = registry.getApplications().iterator().next(); }
assertEquals("http://localhost:80/health", application.getHealthUrl()); @Test
assertEquals("http://localhost:80", application.getManagementUrl()); public void test_register_and_convert() {
assertEquals("http://localhost:80", application.getServiceUrl()); when(discovery.getServices()).thenReturn(Collections.singletonList("service"));
assertEquals("service", application.getName()); when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
} (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
@Test listener.onInstanceRegistered(null);
public void single_discovery_for_same_heartbeat() {
Object heartbeat = new Object(); assertEquals(1, registry.getApplications().size());
listener.onParentHeartbeat(new ParentHeartbeatEvent(new Object(), heartbeat)); Application application = registry.getApplications().iterator().next();
when(discovery.getServices()).thenReturn(Collections.singletonList("service")); assertEquals("http://localhost:80/health", application.getHealthUrl());
when(discovery.getInstances("service")).thenReturn(Collections.singletonList( assertEquals("http://localhost:80", application.getManagementUrl());
(ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false))); assertEquals("http://localhost:80", application.getServiceUrl());
assertEquals("service", application.getName());
listener.onApplicationEvent(new HeartbeatEvent(new Object(), heartbeat)); }
assertEquals(0, registry.getApplications().size());
@Test
listener.onApplicationEvent(new HeartbeatEvent(new Object(), new Object())); public void single_discovery_for_same_heartbeat() {
assertEquals(1, registry.getApplications().size()); Object heartbeat = new Object();
} listener.onParentHeartbeat(new ParentHeartbeatEvent(new Object(), heartbeat));
@Test when(discovery.getServices()).thenReturn(Collections.singletonList("service"));
public void deregister_removed_app() { when(discovery.getInstances("service")).thenReturn(Collections.singletonList(
registry.register(Application.create("ignored").withHealthUrl("http://health") (ServiceInstance) new DefaultServiceInstance("service", "localhost", 80, false)));
.withId("abcdef").build());
registry.register(Application.create("different-source").withHealthUrl("http://health2") listener.onHeartbeat(new HeartbeatEvent(new Object(), heartbeat));
.withId("abcdef").withSource("http-api").build()); assertEquals(0, registry.getApplications().size());
listener.setIgnoredServices(singleton("ignored"));
listener.onHeartbeat(new HeartbeatEvent(new Object(), new Object()));
List<ServiceInstance> instances = new ArrayList<>(); assertEquals(1, registry.getApplications().size());
instances.add(new DefaultServiceInstance("service", "localhost", 80, false)); }
instances.add(new DefaultServiceInstance("service", "example.net", 80, false));
@Test
when(discovery.getServices()).thenReturn(Collections.singletonList("service")); public void deregister_removed_app() {
when(discovery.getInstances("service")).thenReturn(instances); registry.register(Application.create("ignored").withHealthUrl("http://health").withId("abcdef").build());
registry.register(Application.create("different-source")
listener.onApplicationEvent(new HeartbeatEvent(new Object(), new Object())); .withHealthUrl("http://health2")
assertEquals(2, registry.getApplicationsByName("service").size()); .withId("abcdef")
assertEquals(1, registry.getApplicationsByName("ignored").size()); .withSource("http-api")
assertEquals(1, registry.getApplicationsByName("different-source").size()); .build());
listener.setIgnoredServices(singleton("ignored"));
instances.remove(0);
List<ServiceInstance> instances = new ArrayList<>();
listener.onApplicationEvent(new HeartbeatEvent(new Object(), new Object())); instances.add(new DefaultServiceInstance("service", "localhost", 80, false));
assertEquals(1, registry.getApplicationsByName("service").size()); instances.add(new DefaultServiceInstance("service", "example.net", 80, false));
assertEquals(1, registry.getApplicationsByName("ignored").size());
assertEquals(1, registry.getApplicationsByName("different-source").size()); when(discovery.getServices()).thenReturn(Collections.singletonList("service"));
} when(discovery.getInstances("service")).thenReturn(instances);
listener.onHeartbeat(new HeartbeatEvent(new Object(), new Object()));
assertEquals(2, registry.getApplicationsByName("service").size());
assertEquals(1, registry.getApplicationsByName("ignored").size());
assertEquals(1, registry.getApplicationsByName("different-source").size());
instances.remove(0);
listener.onHeartbeat(new HeartbeatEvent(new Object(), new Object()));
assertEquals(1, registry.getApplicationsByName("service").size());
assertEquals(1, registry.getApplicationsByName("ignored").size());
assertEquals(1, registry.getApplicationsByName("different-source").size());
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment