Commit 3e16bad1 by rfelgentraeger Committed by Johannes Edmeier

Add ApplicationFactory

With this commit the concept of an ApplicationFactory is introduced. This allows you to easily modify the information used to register your application at the admin server closes #331
parent 8c83f31a
...@@ -56,7 +56,9 @@ NOTE: In case you are deploying multiple applications to the same JVM and multip ...@@ -56,7 +56,9 @@ NOTE: In case you are deploying multiple applications to the same JVM and multip
[[spring-boot-admin-client]] [[spring-boot-admin-client]]
=== Spring Boot Admin Client === === Spring Boot Admin Client ===
The Spring Boot Admin Client registers the application at the admin server. This is done by periodically doing a http post-request to the admin server providing informations about the application. It also adds Jolokia to your dependencies, so that JMX-beans are accessible via http, this is needed if you want to manage loglevels or JMX-beans via the admin UI. The Spring Boot Admin Client registers the application at the admin server. This is done by periodically doing a http post-request to the admin server providing information about the application. It also adds Jolokia to your dependencies, so that JMX-beans are accessible via http, this is needed if you want to manage loglevels or JMX-beans via the admin UI.
There are plenty of properties to influence the way how the client registers your application. In case that doesn't fit your needs, you can provide your own `AppliationFactory` implementation.
.Spring Boot Admin Client configuration options .Spring Boot Admin Client configuration options
|=== |===
...@@ -115,3 +117,5 @@ spring.boot.admin.password ...@@ -115,3 +117,5 @@ spring.boot.admin.password
| Use the ip-address rather then the hostname in the guessed urls. If `server.address` / `management.address` is set, it get used. Otherwise the IP address returned from `InetAddress.getLocalHost()` gets used. | Use the ip-address rather then the hostname in the guessed urls. If `server.address` / `management.address` is set, it get used. Otherwise the IP address returned from `InetAddress.getLocalHost()` gets used.
| `false` | `false`
|=== |===
----
\ No newline at end of file
...@@ -15,38 +15,25 @@ ...@@ -15,38 +15,25 @@
*/ */
package de.codecentric.boot.admin.client.config; package de.codecentric.boot.admin.client.config;
import static org.springframework.util.StringUtils.trimLeadingCharacter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.event.EventListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.UriComponentsBuilder;
@ConfigurationProperties(prefix = "spring.boot.admin.client") @ConfigurationProperties(prefix = "spring.boot.admin.client")
public class AdminClientProperties { public class AdminClientProperties {
/** /**
* Client-management-URL to register with. Inferred at runtime, can be overriden in case the * Client-management-URL to register with. Inferred at runtime, can be overridden in case the
* reachable URL is different (e.g. Docker). * reachable URL is different (e.g. Docker).
*/ */
private String managementUrl; private String managementUrl;
/** /**
* Client-service-URL register with. Inferred at runtime, can be overriden in case the reachable * Client-service-URL register with. Inferred at runtime, can be overridden in case the reachable
* URL is different (e.g. Docker). * URL is different (e.g. Docker).
*/ */
private String serviceUrl; private String serviceUrl;
/** /**
* Client-health-URL to register with. Inferred at runtime, can be overriden in case the * Client-health-URL to register with. Inferred at runtime, can be overridden in case the
* reachable URL is different (e.g. Docker). Must be unique in registry. * reachable URL is different (e.g. Docker). Must be unique in registry.
*/ */
private String healthUrl; private String healthUrl;
...@@ -62,82 +49,30 @@ public class AdminClientProperties { ...@@ -62,82 +49,30 @@ public class AdminClientProperties {
*/ */
private boolean preferIp = false; private boolean preferIp = false;
@Value("${endpoints.health.path:/${endpoints.health.id:health}}") public String getManagementUrl() {
private String healthEndpointPath; return managementUrl;
@Autowired
private ManagementServerProperties management;
@Autowired
private ServerProperties server;
private Integer serverPort;
private Integer managementPort;
@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
if (event.getApplicationContext() instanceof WebApplicationContext) {
serverPort = event.getApplicationContext().getEnvironment()
.getProperty("local.server.port", Integer.class);
managementPort = event.getApplicationContext().getEnvironment()
.getProperty("local.management.port", Integer.class, serverPort);
} }
public void setManagementUrl(String managementUrl) {
this.managementUrl = managementUrl;
} }
public String getServiceUrl() { public String getServiceUrl() {
if (serviceUrl != null) {
return serviceUrl; return serviceUrl;
} }
if (serverPort == null) { public void setServiceUrl(String serviceUrl) {
throw new IllegalStateException( this.serviceUrl = serviceUrl;
"serviceUrl must be set when deployed to servlet-container");
}
return UriComponentsBuilder.newInstance().scheme(getScheme(server.getSsl()))
.host(getServiceHost()).port(serverPort).path(server.getContextPath())
.toUriString();
}
public String getManagementUrl() {
if (managementUrl != null) {
return managementUrl;
}
if (managementPort == null || managementPort.equals(serverPort)) {
return UriComponentsBuilder.fromHttpUrl(getServiceUrl())
.pathSegment(server.getServletPrefix().split("/"))
.pathSegment(trimLeadingCharacter(management.getContextPath(), '/').split("/"))
.toUriString();
}
Ssl ssl = management.getSsl() != null ? management.getSsl() : server.getSsl();
return UriComponentsBuilder.newInstance().scheme(getScheme(ssl)).host(getManagementHost())
.port(managementPort).path(management.getContextPath()).toUriString();
} }
public String getHealthUrl() { public String getHealthUrl() {
if (healthUrl != null) {
return healthUrl; return healthUrl;
} }
return UriComponentsBuilder.fromHttpUrl(getManagementUrl())
.pathSegment(trimLeadingCharacter(healthEndpointPath, '/').split("/"))
.toUriString();
}
public void setManagementUrl(String managementUrl) {
this.managementUrl = managementUrl;
}
public void setHealthUrl(String healthUrl) { public void setHealthUrl(String healthUrl) {
this.healthUrl = healthUrl; this.healthUrl = healthUrl;
} }
public void setServiceUrl(String serviceUrl) {
this.serviceUrl = serviceUrl;
}
public String getName() { public String getName() {
return name; return name;
} }
...@@ -146,44 +81,11 @@ public class AdminClientProperties { ...@@ -146,44 +81,11 @@ public class AdminClientProperties {
this.name = name; this.name = name;
} }
public void setPreferIp(boolean preferIp) {
this.preferIp = preferIp;
}
public boolean isPreferIp() { public boolean isPreferIp() {
return preferIp; return preferIp;
} }
private String getScheme(Ssl ssl) { public void setPreferIp(boolean preferIp) {
return ssl != null && ssl.isEnabled() ? "https" : "http"; this.preferIp = preferIp;
}
private String getHost(InetAddress address) {
return preferIp ? address.getHostAddress() : address.getCanonicalHostName();
}
private String getServiceHost() {
InetAddress address = server.getAddress();
if (address == null) {
address = getLocalHost();
}
return getHost(address);
}
private String getManagementHost() {
InetAddress address = management.getAddress();
if (address != null) {
return getHost(address);
}
return getServiceHost();
}
private InetAddress getLocalHost() {
try {
return InetAddress.getLocalHost();
} catch (UnknownHostException ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
} }
} }
...@@ -15,9 +15,11 @@ ...@@ -15,9 +15,11 @@
*/ */
package de.codecentric.boot.admin.client.config; package de.codecentric.boot.admin.client.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -28,7 +30,9 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert ...@@ -28,7 +30,9 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import de.codecentric.boot.admin.client.registration.ApplicationFactory;
import de.codecentric.boot.admin.client.registration.ApplicationRegistrator; import de.codecentric.boot.admin.client.registration.ApplicationRegistrator;
import de.codecentric.boot.admin.client.registration.DefaultApplicationFactory;
import de.codecentric.boot.admin.client.registration.RegistrationApplicationListener; import de.codecentric.boot.admin.client.registration.RegistrationApplicationListener;
@Configuration @Configuration
...@@ -36,28 +40,25 @@ import de.codecentric.boot.admin.client.registration.RegistrationApplicationList ...@@ -36,28 +40,25 @@ import de.codecentric.boot.admin.client.registration.RegistrationApplicationList
@Conditional(SpringBootAdminClientEnabledCondition.class) @Conditional(SpringBootAdminClientEnabledCondition.class)
public class SpringBootAdminClientAutoConfiguration { public class SpringBootAdminClientAutoConfiguration {
@Autowired
private AdminClientProperties client;
@Autowired
private AdminProperties admin;
@Autowired
private RestTemplateBuilder restTemplBuilder;
/**
* Task that registers the application at the spring-boot-admin application.
*/
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ApplicationRegistrator registrator() { public ApplicationRegistrator registrator(AdminProperties admin,
ApplicationFactory applicationFactory, RestTemplateBuilder restTemplBuilder) {
RestTemplateBuilder builder = restTemplBuilder RestTemplateBuilder builder = restTemplBuilder
.messageConverters(new MappingJackson2HttpMessageConverter()) .messageConverters(new MappingJackson2HttpMessageConverter())
.requestFactory(SimpleClientHttpRequestFactory.class); .requestFactory(SimpleClientHttpRequestFactory.class);
if (admin.getUsername() != null) { if (admin.getUsername() != null) {
builder = builder.basicAuthorization(admin.getUsername(), admin.getPassword()); builder = builder.basicAuthorization(admin.getUsername(), admin.getPassword());
} }
return new ApplicationRegistrator(builder.build(), admin, client); return new ApplicationRegistrator(builder.build(), admin, applicationFactory);
}
@Bean
@ConditionalOnMissingBean
public ApplicationFactory applicationFactory(AdminClientProperties client,
ManagementServerProperties management, ServerProperties server,
@Value("${endpoints.health.path:/${endpoints.health.id:health}}") String healthEndpointPath) {
return new DefaultApplicationFactory(client, management, server, healthEndpointPath);
} }
@Bean @Bean
...@@ -70,14 +71,12 @@ public class SpringBootAdminClientAutoConfiguration { ...@@ -70,14 +71,12 @@ public class SpringBootAdminClientAutoConfiguration {
return taskScheduler; return taskScheduler;
} }
/**
* ApplicationListener triggering registration after being ready/shutdown
*/
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public RegistrationApplicationListener registrationListener() { public RegistrationApplicationListener registrationListener(AdminProperties admin,
RegistrationApplicationListener listener = new RegistrationApplicationListener( ApplicationRegistrator registrator) {
registrator(), registrationTaskScheduler()); RegistrationApplicationListener listener = new RegistrationApplicationListener(registrator,
registrationTaskScheduler());
listener.setAutoRegister(admin.isAutoRegistration()); listener.setAutoRegister(admin.isAutoRegistration());
listener.setAutoDeregister(admin.isAutoDeregistration()); listener.setAutoDeregister(admin.isAutoDeregistration());
listener.setRegisterPeriod(admin.getPeriod()); listener.setRegisterPeriod(admin.getPeriod());
......
/*
* Copyright 201 6the 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 de.codecentric.boot.admin.client.registration;
/**
* Classes implementing this interface are responsible for creating an {@link Application} class
* which is used to register at the admin server.
*
* @author Johannes Edmeier
*/
public interface ApplicationFactory {
/**
* @return {@link Application} instance;
*/
Application createApplication();
}
\ No newline at end of file
...@@ -28,7 +28,6 @@ import org.springframework.http.MediaType; ...@@ -28,7 +28,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import de.codecentric.boot.admin.client.config.AdminClientProperties;
import de.codecentric.boot.admin.client.config.AdminProperties; import de.codecentric.boot.admin.client.config.AdminProperties;
/** /**
...@@ -37,22 +36,16 @@ import de.codecentric.boot.admin.client.config.AdminProperties; ...@@ -37,22 +36,16 @@ import de.codecentric.boot.admin.client.config.AdminProperties;
public class ApplicationRegistrator { public class ApplicationRegistrator {
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRegistrator.class); private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRegistrator.class);
private static final HttpHeaders HTTP_HEADERS = createHttpHeaders();
private static HttpHeaders HTTP_HEADERS = createHttpHeaders();
private final AtomicReference<String> registeredId = new AtomicReference<>(); private final AtomicReference<String> registeredId = new AtomicReference<>();
private final AdminProperties admin;
private AdminClientProperties client;
private AdminProperties admin;
private final RestTemplate template; private final RestTemplate template;
private final ApplicationFactory applicationFactory;
public ApplicationRegistrator(RestTemplate template, AdminProperties admin, public ApplicationRegistrator(RestTemplate template, AdminProperties admin, ApplicationFactory applicationFactory) {
AdminClientProperties client) {
this.client = client;
this.admin = admin; this.admin = admin;
this.template = template; this.template = template;
this.applicationFactory = applicationFactory;
} }
private static HttpHeaders createHttpHeaders() { private static HttpHeaders createHttpHeaders() {
...@@ -120,8 +113,6 @@ public class ApplicationRegistrator { ...@@ -120,8 +113,6 @@ public class ApplicationRegistrator {
} }
protected Application createApplication() { protected Application createApplication() {
return Application.create(client.getName()).withHealthUrl(client.getHealthUrl()) return applicationFactory.createApplication();
.withManagementUrl(client.getManagementUrl()).withServiceUrl(client.getServiceUrl())
.build();
} }
} }
package de.codecentric.boot.admin.client.registration;
import static org.springframework.util.StringUtils.trimLeadingCharacter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.UriComponentsBuilder;
import de.codecentric.boot.admin.client.config.AdminClientProperties;
/**
* Default implementation for creating the {@link Application} instance which gets registered at the
* admin server.
*
* @author Johannes Edmeier
* @author Rene Felgenträger
*/
public class DefaultApplicationFactory implements ApplicationFactory {
private AdminClientProperties client;
private ServerProperties server;
private ManagementServerProperties management;
private Integer localServerPort;
private Integer localManagementPort;
private String healthEndpointPath;
public DefaultApplicationFactory(AdminClientProperties client,
ManagementServerProperties management, ServerProperties server,
String healthEndpointPath) {
this.client = client;
this.management = management;
this.server = server;
this.healthEndpointPath = healthEndpointPath;
}
@Override
public Application createApplication() {
return Application.create(getName()).withHealthUrl(getHealthUrl())
.withManagementUrl(getManagementUrl()).withServiceUrl(getServiceUrl()).build();
}
protected String getName() {
return client.getName();
}
protected String getServiceUrl() {
if (client.getServiceUrl() != null) {
return client.getServiceUrl();
}
if (getLocalServerPort() == null) {
throw new IllegalStateException(
"serviceUrl must be set when deployed to servlet-container");
}
return UriComponentsBuilder.newInstance().scheme(getScheme(server.getSsl()))
.host(getServiceHost()).port(getLocalServerPort()).path(server.getContextPath())
.toUriString();
}
protected String getManagementUrl() {
if (client.getManagementUrl() != null) {
return client.getManagementUrl();
}
if (getLocalManagementPort() == null
|| getLocalManagementPort().equals(getLocalServerPort())) {
return UriComponentsBuilder.fromHttpUrl(getServiceUrl())
.pathSegment(server.getServletPrefix().split("/"))
.pathSegment(trimLeadingCharacter(management.getContextPath(), '/').split("/"))
.toUriString();
}
Ssl ssl = management.getSsl() != null ? management.getSsl() : server.getSsl();
return UriComponentsBuilder.newInstance().scheme(getScheme(ssl)).host(getManagementHost())
.port(getLocalManagementPort()).path(management.getContextPath()).toUriString();
}
protected String getHealthUrl() {
if (client.getHealthUrl() != null) {
return client.getHealthUrl();
}
return UriComponentsBuilder.fromHttpUrl(getManagementUrl())
.pathSegment(trimLeadingCharacter(getHealthEndpointPath(), '/').split("/"))
.toUriString();
}
protected String getServiceHost() {
InetAddress address = server.getAddress();
if (address == null) {
address = getLocalHost();
}
return getHost(address);
}
protected String getManagementHost() {
InetAddress address = management.getAddress();
if (address != null) {
return getHost(address);
}
return getServiceHost();
}
protected InetAddress getLocalHost() {
try {
return InetAddress.getLocalHost();
} catch (UnknownHostException ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
}
protected Integer getLocalServerPort() {
return localServerPort;
}
protected Integer getLocalManagementPort() {
return localManagementPort;
}
protected String getHealthEndpointPath() {
return healthEndpointPath;
}
protected String getScheme(Ssl ssl) {
return ssl != null && ssl.isEnabled() ? "https" : "http";
}
protected String getHost(InetAddress address) {
return client.isPreferIp() ? address.getHostAddress() : address.getCanonicalHostName();
}
@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
if (event.getApplicationContext() instanceof WebApplicationContext) {
localServerPort = event.getApplicationContext().getEnvironment()
.getProperty("local.server.port", Integer.class);
localManagementPort = event.getApplicationContext().getEnvironment()
.getProperty("local.management.port", Integer.class, localServerPort);
}
}
}
package de.codecentric.boot.admin.client.config;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcManagementContextConfiguration;
import org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import de.codecentric.boot.admin.client.config.AdminClientProperties;
public class AdminClientPropertiesTest {
private AnnotationConfigWebApplicationContext context;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void test_mgmtPortPath() {
load("management.contextPath=/admin", "endpoints.health.id=alive", "local.server.port=8080",
"local.management.port=8081");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(),
is("http://" + getHostname() + ":8081/admin"));
assertThat(clientProperties.getHealthUrl(),
is("http://" + getHostname() + ":8081/admin/alive"));
assertThat(clientProperties.getServiceUrl(), is("http://" + getHostname() + ":8080"));
}
@Test
public void test_contextPath_mgmtPath() {
load("server.context-path=app", "management.context-path=/admin", "local.server.port=8080");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(),
is("http://" + getHostname() + ":8080/app/admin"));
assertThat(clientProperties.getHealthUrl(),
is("http://" + getHostname() + ":8080/app/admin/health"));
assertThat(clientProperties.getServiceUrl(), is("http://" + getHostname() + ":8080/app"));
}
@Test
public void test_contextPatht_mgmtPortPath() {
load("server.context-path=app", "management.context-path=/admin", "local.server.port=8080",
"local.management.port=8081", "endpoints.health.path=/foo/bar");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(),
is("http://" + getHostname() + ":8081/admin"));
assertThat(clientProperties.getHealthUrl(),
is("http://" + getHostname() + ":8081/admin/foo/bar"));
assertThat(clientProperties.getServiceUrl(), is("http://" + getHostname() + ":8080/app"));
}
@Test
public void test_contextPath() {
load("server.context-path=app", "local.server.port=80");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(), is("http://" + getHostname() + ":80/app"));
assertThat(clientProperties.getHealthUrl(),
is("http://" + getHostname() + ":80/app/health"));
assertThat(clientProperties.getServiceUrl(), is("http://" + getHostname() + ":80/app"));
}
@Test
public void test_servletPath() {
load("server.servlet-path=app", "server.context-path=srv", "local.server.port=80");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(),
is("http://" + getHostname() + ":80/srv/app"));
assertThat(clientProperties.getHealthUrl(),
is("http://" + getHostname() + ":80/srv/app/health"));
assertThat(clientProperties.getServiceUrl(), is("http://" + getHostname() + ":80/srv"));
}
@Test
public void test_default() {
load("local.server.port=8080");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(), is("http://" + getHostname() + ":8080"));
assertThat(clientProperties.getHealthUrl(), is("http://" + getHostname() + ":8080/health"));
assertThat(clientProperties.getServiceUrl(), is("http://" + getHostname() + ":8080"));
}
@Test
public void test_ssl() {
load("server.ssl.key-store=somefile.jks", "server.ssl.key-store-password=password",
"local.server.port=8080");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(), is("https://" + getHostname() + ":8080"));
assertThat(clientProperties.getHealthUrl(),
is("https://" + getHostname() + ":8080/health"));
assertThat(clientProperties.getServiceUrl(), is("https://" + getHostname() + ":8080"));
}
@Test
public void test_ssl_managment() {
load("management.ssl.key-store=somefile.jks", "management.ssl.key-store-password=password",
"local.server.port=8080", "local.management.port=9090");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(), is("https://" + getHostname() + ":9090"));
assertThat(clientProperties.getHealthUrl(),
is("https://" + getHostname() + ":9090/health"));
assertThat(clientProperties.getServiceUrl(), is("http://" + getHostname() + ":8080"));
}
@Test
public void test_preferIpAddress_serveraddress_missing() {
load("spring.boot.admin.client.prefer-ip=true", "local.server.port=8080");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertTrue(clientProperties.getServiceUrl()
.matches("http://\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}:8080"));
}
@Test
public void test_preferIpAddress_managementaddress_missing() {
load("spring.boot.admin.client.prefer-ip=true", "local.server.port=8080",
"local.management.port=8081");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertTrue(clientProperties.getManagementUrl()
.matches("http://\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}:8081"));
}
@Test
public void test_preferIpAddress() {
load("spring.boot.admin.client.prefer-ip=true", "server.address=127.0.0.1",
"management.address=127.0.0.2", "local.server.port=8080",
"local.management.port=8081");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getManagementUrl(), is("http://127.0.0.2:8081"));
assertThat(clientProperties.getHealthUrl(), is("http://127.0.0.2:8081/health"));
assertThat(clientProperties.getServiceUrl(), is("http://127.0.0.1:8080"));
}
@Test
public void test_serveraddress() {
load("server.address=127.0.0.2", "local.server.port=8080");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getServiceUrl(), is("http://127.0.0.2:8080"));
assertThat(clientProperties.getManagementUrl(), is("http://127.0.0.2:8080"));
assertThat(clientProperties.getHealthUrl(), is("http://127.0.0.2:8080/health"));
}
@Test
public void test_managementaddress() {
load("server.address=127.0.0.2", "management.address=127.0.0.3", "local.server.port=8080",
"local.management.port=8081");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getServiceUrl(), is("http://127.0.0.2:8080"));
assertThat(clientProperties.getManagementUrl(), is("http://127.0.0.3:8081"));
assertThat(clientProperties.getHealthUrl(), is("http://127.0.0.3:8081/health"));
}
@Test
public void test_allcustom() {
load("spring.boot.admin.client.service-url=http://service",
"spring.boot.admin.client.management-url=http://management",
"spring.boot.admin.client.health-url=http://health");
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
publishApplicationReadyEvent(clientProperties);
assertThat(clientProperties.getServiceUrl(), is("http://service"));
assertThat(clientProperties.getManagementUrl(), is("http://management"));
assertThat(clientProperties.getHealthUrl(), is("http://health"));
}
@Test
public void test_missingports() {
load();
AdminClientProperties clientProperties = context.getBean(AdminClientProperties.class);
try {
clientProperties.getServiceUrl();
fail("IllegalStateException expected");
} catch (IllegalStateException ex) {
assertThat(ex.getMessage(), containsString("serviceUrl"));
}
try {
clientProperties.getManagementUrl();
fail("IllegalStateException expected");
} catch (IllegalStateException ex) {
assertThat(ex.getMessage(), containsString("serviceUrl"));
}
try {
clientProperties.getHealthUrl();
fail("IllegalStateException expected");
} catch (IllegalStateException ex) {
assertThat(ex.getMessage(), containsString("serviceUrl"));
}
}
private String getHostname() {
try {
return InetAddress.getLocalHost().getCanonicalHostName();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
private void publishApplicationReadyEvent(AdminClientProperties client) {
client.onApplicationReady(
new ApplicationReadyEvent(mock(SpringApplication.class), new String[] {}, context));
}
private void load(String... environment) {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(PropertyPlaceholderAutoConfiguration.class);
applicationContext.register(ServerPropertiesAutoConfiguration.class);
applicationContext.register(ManagementServerPropertiesAutoConfiguration.class);
applicationContext.register(EndpointAutoConfiguration.class);
applicationContext.register(EndpointWebMvcManagementContextConfiguration.class);
applicationContext.register(TestConfig.class);
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
applicationContext.refresh();
this.context = applicationContext;
}
@Configuration
@EnableConfigurationProperties({ AdminClientProperties.class })
public static class TestConfig {
}
}
...@@ -36,9 +36,9 @@ import org.springframework.http.ResponseEntity; ...@@ -36,9 +36,9 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import de.codecentric.boot.admin.client.config.AdminClientProperties;
import de.codecentric.boot.admin.client.config.AdminProperties; import de.codecentric.boot.admin.client.config.AdminProperties;
import de.codecentric.boot.admin.client.registration.Application; import de.codecentric.boot.admin.client.registration.Application;
import de.codecentric.boot.admin.client.registration.ApplicationFactory;
import de.codecentric.boot.admin.client.registration.ApplicationRegistrator; import de.codecentric.boot.admin.client.registration.ApplicationRegistrator;
public class ApplicationRegistratorTest { public class ApplicationRegistratorTest {
...@@ -55,13 +55,14 @@ public class ApplicationRegistratorTest { ...@@ -55,13 +55,14 @@ public class ApplicationRegistratorTest {
adminProps = new AdminProperties(); adminProps = new AdminProperties();
adminProps.setUrl(new String[] { "http://sba:8080", "http://sba2:8080" }); adminProps.setUrl(new String[] { "http://sba:8080", "http://sba2:8080" });
AdminClientProperties clientProps = new AdminClientProperties(); ApplicationFactory factory = mock(ApplicationFactory.class);
clientProps.setManagementUrl("http://localhost:8080/mgmt"); when(factory.createApplication()).thenReturn(Application.create("AppName")
clientProps.setHealthUrl("http://localhost:8080/health"); .withManagementUrl("http://localhost:8080/mgmt")
clientProps.setServiceUrl("http://localhost:8080"); .withHealthUrl("http://localhost:8080/health")
clientProps.setName("AppName"); .withServiceUrl("http://localhost:8080")
.build());
registrator = new ApplicationRegistrator(restTemplate, adminProps, clientProps); registrator = new ApplicationRegistrator(restTemplate, adminProps, factory);
headers = new HttpHeaders(); headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); headers.setContentType(MediaType.APPLICATION_JSON);
......
package de.codecentric.boot.admin.registration;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import de.codecentric.boot.admin.client.config.AdminClientProperties;
import de.codecentric.boot.admin.client.registration.Application;
import de.codecentric.boot.admin.client.registration.DefaultApplicationFactory;
public class DefaultApplicationFactoryTest {
private AdminClientProperties client = new AdminClientProperties();
private ServerProperties server = new ServerProperties();
private ManagementServerProperties management = new ManagementServerProperties();
DefaultApplicationFactory factory = new DefaultApplicationFactory(client, management,
server, "/health");
@Before
public void setup() {
client.setName("test");
}
@Test
public void test_mgmtPortPath() {
management.setContextPath("/admin");
DefaultApplicationFactory factory = new DefaultApplicationFactory(client, management,
server, "/alive");
publishApplicationReadyEvent(factory, 8080, 8081);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("http://" + getHostname() + ":8081/admin"));
assertThat(app.getHealthUrl(), is("http://" + getHostname() + ":8081/admin/alive"));
assertThat(app.getServiceUrl(), is("http://" + getHostname() + ":8080"));
}
@Test
public void test_contextPath_mgmtPath() {
server.setContextPath("app");
management.setContextPath("/admin");
publishApplicationReadyEvent(factory, 8080, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("http://" + getHostname() + ":8080/app/admin"));
assertThat(app.getHealthUrl(), is("http://" + getHostname() + ":8080/app/admin/health"));
assertThat(app.getServiceUrl(), is("http://" + getHostname() + ":8080/app"));
}
@Test
public void test_contextPath_mgmtPortPath() {
server.setContextPath("app");
management.setContextPath("/admin");
publishApplicationReadyEvent(factory, 8080, 8081);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("http://" + getHostname() + ":8081/admin"));
assertThat(app.getHealthUrl(), is("http://" + getHostname() + ":8081/admin/health"));
assertThat(app.getServiceUrl(), is("http://" + getHostname() + ":8080/app"));
}
@Test
public void test_contextPath() {
server.setContextPath("app");
publishApplicationReadyEvent(factory, 80, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("http://" + getHostname() + ":80/app"));
assertThat(app.getHealthUrl(), is("http://" + getHostname() + ":80/app/health"));
assertThat(app.getServiceUrl(), is("http://" + getHostname() + ":80/app"));
}
@Test
public void test_servletPath() {
server.setServletPath("app");
server.setContextPath("srv");
publishApplicationReadyEvent(factory, 80, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("http://" + getHostname() + ":80/srv/app"));
assertThat(app.getHealthUrl(), is("http://" + getHostname() + ":80/srv/app/health"));
assertThat(app.getServiceUrl(), is("http://" + getHostname() + ":80/srv"));
}
@Test
public void test_default() {
publishApplicationReadyEvent(factory, 8080, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("http://" + getHostname() + ":8080"));
assertThat(app.getHealthUrl(), is("http://" + getHostname() + ":8080/health"));
assertThat(app.getServiceUrl(), is("http://" + getHostname() + ":8080"));
}
@Test
public void test_ssl() {
server.setSsl(new Ssl());
server.getSsl().setEnabled(true);
publishApplicationReadyEvent(factory, 8080, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("https://" + getHostname() + ":8080"));
assertThat(app.getHealthUrl(), is("https://" + getHostname() + ":8080/health"));
assertThat(app.getServiceUrl(), is("https://" + getHostname() + ":8080"));
}
@Test
public void test_ssl_managment() {
management.setSsl(new Ssl());
management.getSsl().setEnabled(true);
publishApplicationReadyEvent(factory, 8080, 9090);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("https://" + getHostname() + ":9090"));
assertThat(app.getHealthUrl(), is("https://" + getHostname() + ":9090/health"));
assertThat(app.getServiceUrl(), is("http://" + getHostname() + ":8080"));
}
@Test
public void test_preferIpAddress_serveraddress_missing() {
client.setPreferIp(true);
publishApplicationReadyEvent(factory, 8080, null);
Application app = factory.createApplication();
assertTrue(app.getServiceUrl()
.matches("http://\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}:8080"));
}
@Test
public void test_preferIpAddress_managementaddress_missing() {
client.setPreferIp(true);
publishApplicationReadyEvent(factory, 8080, 8081);
Application app = factory.createApplication();
assertTrue(app.getManagementUrl()
.matches("http://\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}:8081"));
}
@Test
public void test_preferIpAddress() throws UnknownHostException {
client.setPreferIp(true);
server.setAddress(InetAddress.getByName("127.0.0.1"));
management.setAddress(InetAddress.getByName("127.0.0.2"));
publishApplicationReadyEvent(factory, 8080, 8081);
Application app = factory.createApplication();
assertThat(app.getManagementUrl(), is("http://127.0.0.2:8081"));
assertThat(app.getHealthUrl(), is("http://127.0.0.2:8081/health"));
assertThat(app.getServiceUrl(), is("http://127.0.0.1:8080"));
}
@Test
public void test_allcustom() {
client.setHealthUrl("http://health");
client.setManagementUrl("http://management");
client.setServiceUrl("http://service");
Application app = factory.createApplication();
assertThat(app.getServiceUrl(), is("http://service"));
assertThat(app.getManagementUrl(), is("http://management"));
assertThat(app.getHealthUrl(), is("http://health"));
}
@Test
public void test_missingports() {
try {
factory.createApplication();
fail("IllegalStateException expected");
} catch (IllegalStateException ex) {
assertThat(ex.getMessage(), containsString("serviceUrl"));
}
}
private String getHostname() {
try {
return InetAddress.getLocalHost().getCanonicalHostName();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
private void publishApplicationReadyEvent(DefaultApplicationFactory factory, Integer serverport,
Integer managementport) {
MockEnvironment env = new MockEnvironment();
if (serverport != null) {
env.setProperty("local.server.port", serverport.toString());
}
if (managementport != null) {
env.setProperty("local.management.port", managementport.toString());
}
ConfigurableWebApplicationContext context = mock(ConfigurableWebApplicationContext.class);
when(context.getEnvironment()).thenReturn(env);
factory.onApplicationReady(
new ApplicationReadyEvent(mock(SpringApplication.class), new String[] {}, context));
}
}
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