Commit b0330cda by Johannes Edmeier

Merge branch '1.3.x'

parents be6d1d41 ba760e20
......@@ -197,7 +197,7 @@ The Spring Boot Admin Client registers the application at the admin server. This
| `true`
| spring.boot.admin.url
| List of URLs of the Spring Boot Admin server to register at. This triggers the AutoConfiguration. *Mandatory*.
| Comma separated ordered list of URLs of the Spring Boot Admin server to register at. This triggers the AutoConfiguration. *Mandatory*.
|
| spring.boot.admin.api-path
......@@ -221,6 +221,10 @@ spring.boot.admin.password
| Switch to enable auto-deregistration at Spring Boot Admin server when context is closed.
| `false`
| spring.boot.admin.register-once
| If set to true the client will only register against one admin server (in order defined by `spring.boot.admin.url`); if that admin server goes down, will automatically register against the next admin server. If false, will register against all admin servers.
| `true`
| spring.boot.admin.client.health-url
| Client-health-url to register with. Can be overridden in case the reachable URL is different (e.g. Docker). Must be unique in registry.
| Guessed based on management-url and `endpoints.health.id`.
......
......@@ -21,7 +21,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
public class AdminProperties {
/**
* The admin servers url to register at
* The admin server urls to register at
*/
private String[] url;
......@@ -55,6 +55,11 @@ public class AdminProperties {
*/
private boolean autoRegistration = true;
/**
* Enable registration against one or all admin servers
*/
private boolean registerOnce = true;
public void setUrl(String[] url) {
this.url = url.clone();
}
......@@ -118,4 +123,12 @@ public class AdminProperties {
public void setAutoRegistration(boolean autoRegistration) {
this.autoRegistration = autoRegistration;
}
public boolean isRegisterOnce() {
return registerOnce;
}
public void setRegisterOnce(boolean registerOnce) {
this.registerOnce = registerOnce;
}
}
......@@ -41,7 +41,7 @@ public class ApplicationRegistrator {
private static HttpHeaders HTTP_HEADERS = createHttpHeaders();
private final AtomicReference<String> registeredId = new AtomicReference<String>();
private final AtomicReference<String> registeredId = new AtomicReference<>();
private AdminClientProperties client;
......@@ -66,26 +66,28 @@ public class ApplicationRegistrator {
/**
* Registers the client application at spring-boot-admin-server.
*
* @return true if successful
* @return true if successful registration on at least one admin server
*/
public boolean register() {
boolean isRegistrationSuccessful = false;
Application self = createApplication();
for (String adminUrl : admin.getAdminUrl()) {
try {
@SuppressWarnings("rawtypes")
ResponseEntity<Map> response = template.postForEntity(adminUrl,
new HttpEntity<Application>(self, HTTP_HEADERS), Map.class);
new HttpEntity<>(self, HTTP_HEADERS), Map.class);
if (response.getStatusCode().equals(HttpStatus.CREATED)) {
if (registeredId.get() == null && registeredId.compareAndSet(null,
response.getBody().get("id").toString())) {
if (registeredId.compareAndSet(null, response.getBody().get("id").toString())) {
LOGGER.info("Application registered itself as {}", response.getBody());
return true;
} else {
LOGGER.debug("Application refreshed itself as {}", response.getBody());
}
LOGGER.debug("Application refreshed itself as {}", response.getBody());
return true;
isRegistrationSuccessful = true;
if (admin.isRegisterOnce()) {
break;
}
} else {
LOGGER.warn("Application failed to registered itself as {}. Response: {}", self,
response.toString());
......@@ -96,7 +98,7 @@ public class ApplicationRegistrator {
}
}
return false;
return isRegistrationSuccessful;
}
public void deregister() {
......@@ -105,8 +107,10 @@ public class ApplicationRegistrator {
for (String adminUrl : admin.getAdminUrl()) {
try {
template.delete(adminUrl + "/" + id);
registeredId.set(null);
return;
registeredId.compareAndSet(id, null);
if (admin.isRegisterOnce()) {
break;
}
} catch (Exception ex) {
LOGGER.warn(
"Failed to deregister application (id={}) at spring-boot-admin ({}): {}",
......
......@@ -42,6 +42,7 @@ import de.codecentric.boot.admin.model.Application;
public class ApplicationRegistratorTest {
private AdminProperties adminProps;
private ApplicationRegistrator registrator;
private RestTemplate restTemplate;
private HttpHeaders headers;
......@@ -50,7 +51,7 @@ public class ApplicationRegistratorTest {
public void setup() {
restTemplate = mock(RestTemplate.class);
AdminProperties adminProps = new AdminProperties();
adminProps = new AdminProperties();
adminProps.setUrl(new String[] { "http://sba:8080", "http://sba2:8080" });
AdminClientProperties clientProps = new AdminClientProperties();
......@@ -76,7 +77,7 @@ public class ApplicationRegistratorTest {
assertTrue(registrator.register());
verify(restTemplate)
.postForEntity("http://sba:8080/api/applications",
new HttpEntity<Application>(Application.create("AppName")
new HttpEntity<>(Application.create("AppName")
.withHealthUrl("http://localhost:8080/health")
.withManagementUrl("http://localhost:8080/mgmt")
.withServiceUrl("http://localhost:8080").build(), headers),
......@@ -114,4 +115,72 @@ public class ApplicationRegistratorTest {
verify(restTemplate).delete("http://sba:8080/api/applications/-id-");
}
@SuppressWarnings("rawtypes")
@Test
public void register_multiple() {
adminProps.setRegisterOnce(false);
when(restTemplate.postForEntity(isA(String.class), isA(HttpEntity.class), eq(Map.class)))
.thenReturn(new ResponseEntity<Map>(Collections.singletonMap("id", "-id-"),
HttpStatus.CREATED));
assertTrue(registrator.register());
verify(restTemplate)
.postForEntity("http://sba:8080/api/applications",
new HttpEntity<>(Application.create("AppName")
.withHealthUrl("http://localhost:8080/health")
.withManagementUrl("http://localhost:8080/mgmt")
.withServiceUrl("http://localhost:8080").build(), headers),
Map.class);
verify(restTemplate)
.postForEntity("http://sba2:8080/api/applications",
new HttpEntity<>(Application.create("AppName")
.withHealthUrl("http://localhost:8080/health")
.withManagementUrl("http://localhost:8080/mgmt")
.withServiceUrl("http://localhost:8080").build(), headers),
Map.class);
}
@SuppressWarnings("rawtypes")
@Test
public void register_multiple_one_failure() {
adminProps.setRegisterOnce(false);
when(restTemplate.postForEntity(isA(String.class), isA(HttpEntity.class), eq(Map.class)))
.thenReturn(new ResponseEntity<Map>(Collections.singletonMap("id", "-id-"),
HttpStatus.CREATED))
.thenThrow(new RestClientException("Error"));
assertTrue(registrator.register());
verify(restTemplate)
.postForEntity("http://sba:8080/api/applications",
new HttpEntity<>(Application.create("AppName")
.withHealthUrl("http://localhost:8080/health")
.withManagementUrl("http://localhost:8080/mgmt")
.withServiceUrl("http://localhost:8080").build(), headers),
Map.class);
verify(restTemplate)
.postForEntity("http://sba2:8080/api/applications",
new HttpEntity<>(Application.create("AppName")
.withHealthUrl("http://localhost:8080/health")
.withManagementUrl("http://localhost:8080/mgmt")
.withServiceUrl("http://localhost:8080").build(), headers),
Map.class);
}
@Test
public void register_multiple_all_failures() {
adminProps.setRegisterOnce(false);
when(restTemplate.postForEntity(isA(String.class), isA(HttpEntity.class), eq(Map.class)))
.thenThrow(new RestClientException("Error"))
.thenThrow(new RestClientException("Error"));
assertFalse(registrator.register());
}
}
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