Skip to content
This repository has been archived by the owner on Aug 18, 2023. It is now read-only.

Commit

Permalink
Merge pull request #7 from department-of-veterans-affairs/dashboard-u…
Browse files Browse the repository at this point in the history
…rl-updates

Dashboard url updates
  • Loading branch information
abhijitvk authored Dec 15, 2017
2 parents 0530bca + 4fa8615 commit cdfec43
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 76 deletions.
5 changes: 4 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- spring cloud dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package gov.va.ascent.dashboard;

import de.codecentric.boot.admin.config.EnableAdminServer;
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
Expand All @@ -9,6 +17,7 @@
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.context.annotation.Configuration;
Expand All @@ -24,13 +33,7 @@
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import de.codecentric.boot.admin.config.EnableAdminServer;

/**
* An <tt>Ascent Dashboard Application</tt> enabled for Spring Boot Application,
Expand All @@ -45,6 +48,7 @@
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
@EnableFeignClients
@Import(TurbineConfiguration.class)
public class AscentDashboardApplication extends WebSecurityConfigurerAdapter {

Expand Down
95 changes: 52 additions & 43 deletions src/main/java/gov/va/ascent/dashboard/DashboardController.java
Original file line number Diff line number Diff line change
@@ -1,96 +1,90 @@
package gov.va.ascent.dashboard;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;

/**
* An <tt>Ascent Dashboard Controller</tt> to generate and serve the misc. dashboard URL requests
*
*/
@Controller
@RefreshScope
public class DashboardController {

private static final Logger LOGGER = LoggerFactory.getLogger(DashboardController.class);

private static final String REST_API = "REST-API";
private static final String APP_TYPE = "appType";
private static final String API = "api/";

@Value("${kibana.url:http://localhost:5601}")
private String kibanaUrl;

@Value("${zipkin.url:http://localhost:8700}")
@Value("${zipkin.url:http://localhost:8700/zipkin/}")
private String zipkinUrl;

@Value("${gateway.url:http://localhost:8762}")
private String gatewayUrl;

@Autowired
private DiscoveryClient discoveryClient;

@Autowired
private GatewayRoutesClient gatewayRoutesClient;

@RequestMapping("/")
public String index() {
public String index(Model model) {
model.addAttribute("zipkinUrl", zipkinUrl);
model.addAttribute("kibanaUrl", kibanaUrl);
return "index";
}

@RequestMapping("/zipkin")
public void zipkin(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (zipkinUrl != null) {
response.sendRedirect(zipkinUrl);
}
}

@RequestMapping("/kibana")
public void kibana(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (kibanaUrl != null) {
response.sendRedirect(kibanaUrl);
}
}

@RequestMapping("/swagger-dash")
public String swagger(Model model) {
final ServiceInstance zuulInstance = getServiceInstance("ascent-gateway");

final Map<String, String> swaggerApps = new TreeMap<>();

final Map<String, List<String>> swaggerApps = new TreeMap<>();
final Map<String, String> routes = getRoutes();
LOGGER.error(Arrays.toString(routes.entrySet().toArray()));
discoveryClient.getServices().forEach((String service) -> {

final ServiceInstance firstServiceInstance = getFirstServiceInstance(service);

if(firstServiceInstance != null
&& REST_API.equals(firstServiceInstance.getMetadata().get(APP_TYPE))){
swaggerApps.put(firstServiceInstance.getServiceId().toLowerCase(),
ServletUriComponentsBuilder.fromUri(zuulInstance.getUri())
.path(API)
.path(firstServiceInstance.getServiceId().toLowerCase())
.path("/swagger-ui.html")
.build().toUriString());
routes.forEach((route, serviceId) -> {
if(StringUtils.equalsIgnoreCase(serviceId,firstServiceInstance.getServiceId())) {
if(swaggerApps.get(firstServiceInstance.getServiceId().toLowerCase()) == null){
swaggerApps.put(firstServiceInstance.getServiceId().toLowerCase(), new ArrayList<>());
}
swaggerApps.get(firstServiceInstance.getServiceId().toLowerCase())
.add(gatewayUrl + route + "swagger-ui.html");
}
});
}
});

model.addAttribute("swaggerApps", swaggerApps);
model.addAttribute("currentPageTitle", "Swagger URLs");
model.addAttribute("zipkinUrl", zipkinUrl);
model.addAttribute("kibanaUrl", kibanaUrl);
return "swagger";
}

private ServiceInstance getServiceInstance(final String serviceName){
ServiceInstance desiredServiceInstance = null;

for(ServiceInstance serviceInstance: discoveryClient.getInstances(serviceName)){
desiredServiceInstance = serviceInstance;
break;
}
return desiredServiceInstance;
}

/**
* Returns the first instance of the provided service name using the DiscoveryClient.
*
Expand All @@ -105,5 +99,20 @@ private ServiceInstance getFirstServiceInstance(String service){
return discoveryClient.getInstances(service).get(0);
}
}

/**
* Returns the routes available on Ascent Gateway
*
* @return map of the routes to service Id
*/
private Map<String, String> getRoutes(){
final Map<String, String> uneditedRoutes = gatewayRoutesClient.getRoutes();
final Map<String, String> routes = new HashMap<>();
uneditedRoutes.forEach((route, service) -> {
final String routeWithoutAsterisk = route.replace("*", "");
routes.put(routeWithoutAsterisk, service);
});
return routes;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package gov.va.ascent.dashboard;

import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignClientConfiguration {

@Value("${security.user.name:admin}")
private String username;

@Value("${security.user.password:default}")
private String password;

@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor(username, password);
}
}
17 changes: 17 additions & 0 deletions src/main/java/gov/va/ascent/dashboard/GatewayRoutesClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package gov.va.ascent.dashboard;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.Map;


@FeignClient(value="ascent-gateway", configuration = FeignClientConfiguration.class)
@FunctionalInterface
public interface GatewayRoutesClient {

@RequestMapping(value = "/actuator/routes", method = RequestMethod.GET)
Map<String, String> getRoutes();

}
6 changes: 3 additions & 3 deletions src/main/resources/templates/fragments/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@
<a class="nav-link" th:classappend="${currentPage == null} ? active : ''" href="/">Home <span th:if="${currentPage == ''}" class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/manage" target="_blank">Spring Boot Admin (SBA)</a>
<a class="nav-link" href="/manage/#/" target="_blank">Spring Boot Admin (SBA)</a>
</li>
<li class="nav-item">
<a class="nav-link" th:classappend="${currentPage == 'Swagger URLs'} ? active : ''" href="swagger-dash">Swagger <span th:if="${currentPage == 'swagger'}" class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/zipkin" target="_blank">Zipkin</a>
<a class="nav-link" th:href="${zipkinUrl}" target="_blank">Zipkin</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/kibana" target="_blank">Kibana</a>
<a class="nav-link" th:href="${kibanaUrl}" target="_blank">Kibana</a>
</li>
</ul>
</nav>
Expand Down
6 changes: 3 additions & 3 deletions src/main/resources/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ <h1 class="display-4">Ascent - Dashboard</h1>

<div class="row marketing">
<div class="col-lg-6">
<h4><a href="/manage" target="_blank">Spring Boot Admin Dashboard</a></h4>
<h4><a href="/manage/#/" target="_blank">Spring Boot Admin Dashboard</a></h4>
<p>Monitoring and Administration of all Discovery Client Applications</p>
<h4><a href="/zipkin" target="_blank">Zipkin</a></h4>
<h4><a th:href="${zipkinUrl}" target="_blank">Zipkin</a></h4>
<p>Zipkin is a distributed tracing system</p>
</div>
<div class="col-lg-6">
<h4><a href="swagger-dash">Swagger Dashboard</a></h4>
<p>Aggregated Swagger Dashboard URLs</p>
<h4><a href="/kibana" target="_blank">Kibana</a></h4>
<h4><a th:href="${kibanaUrl}" target="_blank">Kibana</a></h4>
<p>Review log data for Ascent Platform</p>
</div>
</div>
Expand Down
13 changes: 10 additions & 3 deletions src/main/resources/templates/swagger.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head th:include="fragments/header :: head (${currentPageTitle})"></head>
<head th:include="fragments/header :: head (${currentPageTitle})">

</head>

<body>
<div class="container">
Expand All @@ -15,8 +17,13 @@ <h1 class="display-4"> Swagger URLs</h1>
<div class="row marketing">
<div class="col-lg-12">
<ul class="list-group">
<li th:each="swaggerApp : ${swaggerApps}" class="list-group-item">
<a th:href="${swaggerApp.value}" th:text="${swaggerApp.key}"></a>
<li th:inline="text" th:each="swaggerApp : ${swaggerApps}" class="list-group-item">
[[${swaggerApp.key}]]
<ul class="list-group">
<span th:each="route : ${swaggerApp.value}">
<li><a href="#" th:href="${route}" th:text="${route}"></a></li>
</span>
</ul>
</li>
</ul>
</div>
Expand Down
Loading

0 comments on commit cdfec43

Please sign in to comment.