Commit 45d44aa8 by Johannes Stelzer

Rework default management-url computation.

This change not only allows you to use `context-path` and `contextPath` but also respects automatic port assignment when using `server.port=0` or `managment.port=0`. Also corrects the value if server.port != mangement.port and server.context-path and management.server-path is set. fixes #57
parent 27325103
......@@ -15,23 +15,71 @@
*/
package de.codecentric.boot.admin.config;
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.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationListener;
import org.springframework.util.StringUtils;
@ConfigurationProperties(prefix = "spring.boot.admin.client", ignoreUnknownFields = false)
public class AdminClientProperties {
public class AdminClientProperties implements ApplicationListener<EmbeddedServletContainerInitializedEvent>{
@Value("http://#{T(java.net.InetAddress).localHost.canonicalHostName}:${management.port:${server.port:8080}}${server.context-path:/}${management.context-path:/}")
private String url;
@Value("${spring.application.name:spring-boot-application}")
private String name;
@Autowired
private ManagementServerProperties management;
@Autowired
private ServerProperties server;
private int serverPort = -1;
private int managementPort = -1;
@Override
public void onApplicationEvent(
EmbeddedServletContainerInitializedEvent event) {
if ("management".equals(event.getApplicationContext().getNamespace())) {
managementPort = event.getEmbeddedServletContainer().getPort();
} else {
serverPort = event.getEmbeddedServletContainer().getPort();
}
}
/**
* @return Client-management-URL to register with. Can be overriden in case the
* reachable URL is different (e.g. Docker). Must be unique in registry.
*/
public String getUrl() {
if (url == null) {
if (managementPort != -1) {
url = "http://"
+ (getHostname() + ':' + managementPort + toPathFragment(management
.getContextPath()))
.replaceAll("//+", "/");
} else if (serverPort != -1){
url = "http://"
+ (getHostname()
+ ':'
+ serverPort
+ toPathFragment(server.getContextPath()) + toPathFragment(management
.getContextPath())).replaceAll("//+", "/");
} else {
throw new IllegalStateException(
"EmbeddedServletContainer has not been initialized yet!");
}
}
return url;
}
......@@ -49,4 +97,22 @@ public class AdminClientProperties {
public void setName(String name) {
this.name = name;
}
private String getHostname() {
try {
return InetAddress.getLocalHost().getCanonicalHostName();
}
catch (UnknownHostException ex) {
throw new IllegalStateException("Couldn't get hostname", ex);
}
}
private String toPathFragment(String fragment) {
if (StringUtils.isEmpty(fragment)) {
return "";
}
else {
return "/" + fragment;
}
}
}
package de.codecentric.boot.admin.config;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
public class AdminClientPropertiesTest {
private AnnotationConfigWebApplicationContext context;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void test_mgmtPortPath() {
load("spring.boot.admin.url:http://localhost:8081",
"management.contextPath=/admin");
AdminClientProperties clientProperties = context
.getBean(AdminClientProperties.class);
publishEvent(8080, null);
publishEvent(8081, "management");
assertThat(clientProperties.getUrl(), is("http://" + getHostname()
+ ":8081/admin"));
}
@Test
public void test_mgmtPort() {
load("spring.boot.admin.url:http://localhost:8081");
AdminClientProperties clientProperties = context
.getBean(AdminClientProperties.class);
publishEvent(8080, null);
publishEvent(8081, "management");
assertThat(clientProperties.getUrl(), is("http://" + getHostname() + ":8081"));
}
@Test
public void test_contextPath_mgmtPath() {
load("spring.boot.admin.url:http://localhost:8081", "server.context-path=app",
"management.context-path=/admin");
AdminClientProperties clientProperties = context
.getBean(AdminClientProperties.class);
publishEvent(8080, null);
assertThat(clientProperties.getUrl(), is("http://" + getHostname()
+ ":8080/app/admin"));
}
@Test
public void test_contextPath() {
load("spring.boot.admin.url:http://localhost:8081", "server.context-path=app");
AdminClientProperties clientProperties = context
.getBean(AdminClientProperties.class);
publishEvent(8080, null);
assertThat(clientProperties.getUrl(), is("http://" + getHostname() + ":8080/app"));
}
@Test
public void test_default() {
load("spring.boot.admin.url:http://localhost:8081");
AdminClientProperties clientProperties = context
.getBean(AdminClientProperties.class);
publishEvent(8080, null);
assertThat(clientProperties.getUrl(), is("http://" + getHostname() + ":8080"));
}
private String getHostname() {
try {
return InetAddress.getLocalHost().getCanonicalHostName();
}
catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
private void publishEvent(int port, String namespace) {
EmbeddedServletContainer eventSource = mock(EmbeddedServletContainer.class);
when(eventSource.getPort()).thenReturn(port);
EmbeddedWebApplicationContext eventContext = mock(EmbeddedWebApplicationContext.class);
when(eventContext.getNamespace()).thenReturn(namespace);
context.publishEvent(new EmbeddedServletContainerInitializedEvent(eventContext,
eventSource));
}
private void load(String... environment) {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(ServerPropertiesAutoConfiguration.class);
applicationContext.register(ManagementServerPropertiesAutoConfiguration.class);
applicationContext.register(SpringBootAdminClientAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
applicationContext.refresh();
this.context = applicationContext;
}
}
......@@ -4,6 +4,7 @@ import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
......@@ -53,6 +54,7 @@ public class SpringBootAdminClientAutoConfigurationTest {
private void load(String... environment) {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(ServerPropertiesAutoConfiguration.class);
applicationContext.register(ManagementServerPropertiesAutoConfiguration.class);
applicationContext.register(SpringBootAdminClientAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
applicationContext.refresh();
......
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