diff --git a/.travis.yml b/.travis.yml
index 63f8e2a7..a2e3df25 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@ install:
- mvn --settings .settings.xml install -P docs -q -U -DskipTests=true -Dmaven.test.redirectTestOutputToFile=true
- ./docs/src/main/asciidoc/ghpages.sh
script:
-- ./consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul &
+- ./consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -ui-dir ./src/test/resources/consul_ui &
- '[ "${TRAVIS_PULL_REQUEST}" != "false" ] || mvn --settings .settings.xml deploy -nsu -Dmaven.test.redirectTestOutputToFile=true'
- '[ "${TRAVIS_PULL_REQUEST}" = "false" ] || mvn --settings .settings.xml install -nsu -Dmaven.test.redirectTestOutputToFile=true'
env:
diff --git a/docs/src/main/asciidoc/spring-cloud-consul.adoc b/docs/src/main/asciidoc/spring-cloud-consul.adoc
index c878f2c2..05cc08b1 100644
--- a/docs/src/main/asciidoc/spring-cloud-consul.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-consul.adoc
@@ -161,3 +161,27 @@ spring:
== Spring Cloud Bus with Consul
TODO: document Spring Cloud Consul Bus
+
+
+[[spring-cloud-consul-ui]]
+== Proxy Consul UI through Spring Cloud Application
+
+To enable the Consul Web UI please read https://www.consul.io/intro/getting-started/ui.html[the documentation] under the "Self-hosted Dashboard" section.
+
+After you have enabled the Consul Web UI in the Agent, place the `@EnableConsulUi` annotation on a `@Configuration` class. `@EnableConsulUi` enables a zuul proxy configured to proxy to the Consul UI running on the Consul Agent. The UI will be available by default at `/consul/ui/`. To change the prefix the UI will be available under, set the `spring.cloud.consul.ui.path` property.
+
+.application.yml
+----
+spring:
+ cloud:
+ consul:
+ ui:
+ path: /admin/**
+----
+
+This will make the Web UI available under `/admin/ui/`.
+
+By exposing the Consul Web UI via a Spring Boot application, you can secure access to it via the same Spring Security tools that you use to secure the rest of the application.
+
+[CAUTION]
+The Consul Admin UI expects the Consul HTTP API to be available at `/v1`. If the `server.contextPath` is not `/` or your application has a route at `/v1`, then the Consul Web UI will fail to proxy.
diff --git a/spring-cloud-consul-ui/pom.xml b/spring-cloud-consul-ui/pom.xml
index 1a2a0114..b91e8b2c 100644
--- a/spring-cloud-consul-ui/pom.xml
+++ b/spring-cloud-consul-ui/pom.xml
@@ -40,6 +40,11 @@
spring-boot-starter-test
test
+
+ com.ecwid.consul
+ consul-api
+ test
+
diff --git a/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiConfiguration.java b/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiConfiguration.java
index df0a6787..4b631e41 100644
--- a/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiConfiguration.java
+++ b/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiConfiguration.java
@@ -24,10 +24,12 @@ import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
/**
* @author Spencer Gibb
*/
+@Configuration
@EnableZuulProxy
public class ConsulUiConfiguration {
@@ -44,15 +46,20 @@ public class ConsulUiConfiguration {
public void init() {
String url = String.format("http://%s:%s", consulProperties.getHost(),
consulProperties.getPort());
- ZuulProperties.ZuulRoute route = new ZuulProperties.ZuulRoute("consulUi",
+
+ ZuulProperties.ZuulRoute route = new ZuulProperties.ZuulRoute("consulApi",
"/v1/**", null, url, false, false);
+ zuulProperties.getRoutes().put("consulApi", route);
+
+ route = new ZuulProperties.ZuulRoute("consulUi",
+ "/consul/**", null, url, true, false);
zuulProperties.getRoutes().put("consulUi", route);
zuulHandlerMapping.registerHandlers();
}
@Bean
- public ConsulUiController consulUiController() {
- return new ConsulUiController();
+ public ConsulUiProperties consulUiProperties() {
+ return new ConsulUiProperties();
}
}
diff --git a/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiController.java b/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiProperties.java
similarity index 64%
rename from spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiController.java
rename to spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiProperties.java
index de559934..82cdbce7 100644
--- a/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiController.java
+++ b/spring-cloud-consul-ui/src/main/java/org/springframework/cloud/ui/ConsulUiProperties.java
@@ -16,19 +16,15 @@
package org.springframework.cloud.ui;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
+import lombok.Data;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author Spencer Gibb
*/
-@Controller
-@RequestMapping("${spring.cloud.consul.ui.path:/ui}")
-public class ConsulUiController {
-
- @RequestMapping(method = RequestMethod.GET)
- public String index() {
- return "forward:index.html";
- }
+@ConfigurationProperties("spring.cloud.consul.ui")
+@Data
+public class ConsulUiProperties {
+ private String path = "/consul/**";
}
diff --git a/spring-cloud-consul-ui/src/test/java/org/springframework/cloud/ui/EnableConsulUiTests.java b/spring-cloud-consul-ui/src/test/java/org/springframework/cloud/ui/EnableConsulUiTests.java
new file mode 100644
index 00000000..14b663c1
--- /dev/null
+++ b/spring-cloud-consul-ui/src/test/java/org/springframework/cloud/ui/EnableConsulUiTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013-2015 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.
+ * 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 org.springframework.cloud.ui;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.WebIntegrationTest;
+import org.springframework.cloud.consul.ConsulAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Spencer Gibb
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringApplicationConfiguration(classes = TestConfig.class)
+@WebIntegrationTest(value = "spring.application.name=myTestService", randomPort = true)
+public class EnableConsulUiTests {
+
+ @Value("${local.server.port}")
+ private int port;
+
+ @Test
+ public void consulWebUiWorks() {
+ ResponseEntity response = new TestRestTemplate().getForEntity("http://localhost:" + port + "/consul/ui/", String.class);
+ assertEquals("Wrong response code", HttpStatus.OK, response.getStatusCode());
+ String body = response.getBody();
+ assertNotNull("Null body", body);
+ assertTrue("Missing body text", body.toLowerCase().contains("consul") && body.toLowerCase().contains("services"));
+ }
+
+}
+
+@Configuration
+@EnableAutoConfiguration
+@Import({ ConsulAutoConfiguration.class })
+@EnableConsulUi
+class TestConfig {
+
+}
\ No newline at end of file
diff --git a/src/main/bash/local_run_consul.sh b/src/main/bash/local_run_consul.sh
index af5b5936..876422f3 100755
--- a/src/main/bash/local_run_consul.sh
+++ b/src/main/bash/local_run_consul.sh
@@ -1,2 +1,2 @@
#!/bin/bash
-consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -ui-dir `dirname $0`/../../../spring-cloud-consul-ui/src/main/resources/public
+consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -ui-dir `dirname $0`/../../../src/test/resources/consul_ui
diff --git a/spring-cloud-consul-ui/src/main/resources/public/index.html b/src/test/resources/consul_ui/index.html
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/index.html
rename to src/test/resources/consul_ui/index.html
diff --git a/spring-cloud-consul-ui/src/main/resources/public/static/application.min.js b/src/test/resources/consul_ui/static/application.min.js
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/static/application.min.js
rename to src/test/resources/consul_ui/static/application.min.js
diff --git a/spring-cloud-consul-ui/src/main/resources/public/static/base.css b/src/test/resources/consul_ui/static/base.css
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/static/base.css
rename to src/test/resources/consul_ui/static/base.css
diff --git a/spring-cloud-consul-ui/src/main/resources/public/static/base.css.map b/src/test/resources/consul_ui/static/base.css.map
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/static/base.css.map
rename to src/test/resources/consul_ui/static/base.css.map
diff --git a/spring-cloud-consul-ui/src/main/resources/public/static/bootstrap.min.css b/src/test/resources/consul_ui/static/bootstrap.min.css
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/static/bootstrap.min.css
rename to src/test/resources/consul_ui/static/bootstrap.min.css
diff --git a/spring-cloud-consul-ui/src/main/resources/public/static/consul-logo.png b/src/test/resources/consul_ui/static/consul-logo.png
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/static/consul-logo.png
rename to src/test/resources/consul_ui/static/consul-logo.png
diff --git a/spring-cloud-consul-ui/src/main/resources/public/static/favicon.png b/src/test/resources/consul_ui/static/favicon.png
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/static/favicon.png
rename to src/test/resources/consul_ui/static/favicon.png
diff --git a/spring-cloud-consul-ui/src/main/resources/public/static/loading-cylon-purple.svg b/src/test/resources/consul_ui/static/loading-cylon-purple.svg
similarity index 100%
rename from spring-cloud-consul-ui/src/main/resources/public/static/loading-cylon-purple.svg
rename to src/test/resources/consul_ui/static/loading-cylon-purple.svg