From b9708a7c3cfaf5767992a2b15180e7b85c459242 Mon Sep 17 00:00:00 2001 From: "Eran (ev672n), Vosk" Date: Tue, 7 Aug 2018 14:15:05 +0300 Subject: adding the dcae dt code Adding DCAE-dt code Change-Id: Id6b779db9d24e10825fb97ad5fd46f41e65e6738 Issue-ID: SDC-1614 Signed-off-by: Eran (ev672n), Vosk --- src/main/java/org/onap/sdc/dcae/FeApp.java | 76 ++++++++++ .../dcae/controller/health/HealthController.java | 72 +++++++++ .../sdc/dcae/controller/proxy/DcaeProxyOld.java | 164 +++++++++++++++++++++ .../sdc/dcae/controller/proxy/DcaeProxyTest.java | 29 ++++ 4 files changed, 341 insertions(+) create mode 100644 src/main/java/org/onap/sdc/dcae/FeApp.java create mode 100644 src/main/java/org/onap/sdc/dcae/controller/health/HealthController.java create mode 100644 src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxyOld.java create mode 100644 src/test/org/onap/sdc/dcae/controller/proxy/DcaeProxyTest.java (limited to 'src') diff --git a/src/main/java/org/onap/sdc/dcae/FeApp.java b/src/main/java/org/onap/sdc/dcae/FeApp.java new file mode 100644 index 0000000..c2e3bc9 --- /dev/null +++ b/src/main/java/org/onap/sdc/dcae/FeApp.java @@ -0,0 +1,76 @@ +package org.onap.sdc.dcae; + +import org.onap.sdc.dcae.controller.proxy.DcaeProxyOld; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.context.annotation.*; + +import javax.servlet.ServletContext; +import java.io.IOException; +import java.io.InputStream; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + + +@Configuration +@ComponentScan() +@EnableAutoConfiguration +@PropertySource("file:${jetty.base}/config/dcae-dt/application.properties") +public class FeApp extends SpringBootServletInitializer implements CommandLineRunner{ + + private static final String SPECIFICATION_VERSION = "Specification-Version"; + @Autowired + ServletContext servletContext; + + private static final String MANIFEST_FILE_NAME = "/META-INF/MANIFEST.MF"; + private static String dcaeVersion; + + @Value("${newFeUrl}") + private String newFeUrl; + + @Value("${newFeContextPath}") + private String newFeContextPath; + + public static void main(String[] args) { + SpringApplication.run(FeApp.class, args); + } + + public void run(String... arg0) throws Exception { + InputStream inputStream = servletContext.getResourceAsStream(MANIFEST_FILE_NAME); + + System.out.println("Server is starting..reading DCAE version..."); + + String version = null; + try { + Manifest mf = new Manifest(inputStream); + Attributes atts = mf.getMainAttributes(); + version = atts.getValue(SPECIFICATION_VERSION); + if (version == null || version.isEmpty()) { + System.err.println("failed to read DCAE version from MANIFEST."); + } else { + System.out.println("DCAE version from MANIFEST is "+ version); + dcaeVersion = version; + } + + } catch (IOException e) { + System.err.println("failed to read DCAE version from MANIFEST: "+ e.getMessage()); + } + } + + public static String getDcaeVersion() { + return dcaeVersion; + } + + + @Bean + public ServletRegistrationBean dcaeProxyBean() { + ServletRegistrationBean bean = new ServletRegistrationBean(new DcaeProxyOld(newFeUrl, newFeContextPath), "/dcaeProxyOld/*"); + bean.setLoadOnStartup(1); + return bean; + } +} diff --git a/src/main/java/org/onap/sdc/dcae/controller/health/HealthController.java b/src/main/java/org/onap/sdc/dcae/controller/health/HealthController.java new file mode 100644 index 0000000..9086600 --- /dev/null +++ b/src/main/java/org/onap/sdc/dcae/controller/health/HealthController.java @@ -0,0 +1,72 @@ +package org.onap.sdc.dcae.controller.health; + +import java.util.ArrayList; +import java.util.List; + +import org.onap.sdc.dcae.FeApp; +import org.onap.sdc.dcae.composition.restmodels.health.ComponentsInfo; +import org.onap.sdc.dcae.composition.restmodels.health.HealthResponse; +import org.onap.sdc.dcae.composition.util.DcaeFeConstants; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import com.google.gson.Gson; + + +/** + * + * @author lezer + * Example: + * { + "healthCheckComponent": "DCAE Designer", + "healthCheckStatus": "UP", + "description": "OK", + "componentsInfo": [{ + "healthCheckComponent": "FE", + "healthCheckStatus": "UP", + "description": "OK" + }] +} + * + */ +@RestController +@EnableAutoConfiguration +@CrossOrigin +public class HealthController { + Gson gson = new Gson(); + + @RequestMapping(value = "/healthCheckOld", method = RequestMethod.GET) + public ResponseEntity healthCheck() { + try{ + HealthResponse healthResponse = new HealthResponse(); + healthResponse.setHealthCheckComponent(DcaeFeConstants.Health.APP_NAME); + healthResponse.setHealthCheckStatus(DcaeFeConstants.Health.UP); + healthResponse.setSdcVersion(FeApp.getDcaeVersion()); + healthResponse.setDescription(DcaeFeConstants.Health.OK); + + List componentsInfoList = new ArrayList(); + ComponentsInfo componentsInfo = new ComponentsInfo(); + componentsInfo.setHealthCheckComponent(DcaeFeConstants.Health.FE); + componentsInfo.setHealthCheckStatus(DcaeFeConstants.Health.UP); + componentsInfo.setVersion(FeApp.getDcaeVersion()); + componentsInfo.setDescription(DcaeFeConstants.Health.OK); + componentsInfoList.add(componentsInfo); + + healthResponse.setComponentsInfo(componentsInfoList); + String json = gson.toJson(healthResponse, HealthResponse.class); + System.out.println("Health Check response: "+json); + + return new ResponseEntity(json, HttpStatus.OK); + } + catch(Exception e){ + System.err.println("Error occured while performing HealthCheck: "+e.getLocalizedMessage()); + return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + +} diff --git a/src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxyOld.java b/src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxyOld.java new file mode 100644 index 0000000..cacb092 --- /dev/null +++ b/src/main/java/org/onap/sdc/dcae/controller/proxy/DcaeProxyOld.java @@ -0,0 +1,164 @@ +package org.onap.sdc.dcae.controller.proxy; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.proxy.ProxyServlet; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.springframework.util.StringUtils; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.concurrent.TimeUnit; + + +public class DcaeProxyOld extends ProxyServlet { + + private static Logger log = LoggerFactory.getLogger(DcaeProxyOld.class); + private static Cache mdcDataCache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build(); + + + //TODO proper configuration class + private String newFeUrl; + private String newFeContextPath; + + public DcaeProxyOld(String newFeUrl, String newFeContextPath){ + this.newFeUrl = newFeUrl; + this.newFeContextPath = newFeContextPath; + } + + @Override + protected HttpClient newHttpClient() { + SslContextFactory factory = new SslContextFactory(true); + return new HttpClient(factory); + } + + @Override + protected HttpClient createHttpClient() throws ServletException { + HttpClient client = super.createHttpClient(); + client.setIdleTimeout(180000); + client.setConnectTimeout(180000); + return client; + } + + @Override + protected String rewriteTarget(HttpServletRequest request) { + try{ + logRequest(request); + }catch (Exception e){ + log.error("Unexpected FE request logging error :", e); + } + String uri = request.getRequestURI(); + uri = uri.replace("/dcaeProxyOld", "/dcaeProxy"); + uri = uri.replaceFirst("/dcae", newFeContextPath); + String query = request.getQueryString(); + StringBuilder url = new StringBuilder(); + url.append(newFeUrl).append(uri); + if(null != query) + url.append("?").append(query); + String urlString = url.toString(); + log.info("Proxy outgoing request={}", urlString); + return urlString; + } + + @Override + protected void onProxyResponseSuccess(HttpServletRequest clientRequest, HttpServletResponse proxyResponse, Response serverResponse) { + try{ + logResponse(clientRequest, serverResponse); + }catch (Exception e){ + log.error("Unexpected FE response logging error :", e); + } + super.onProxyResponseSuccess(clientRequest, proxyResponse, serverResponse); + } + + + private void logRequest(HttpServletRequest httpRequest) { + MDC.clear(); + Long transactionStartTime = System.currentTimeMillis(); + String requestId = httpRequest.getHeader("X-ECOMP-RequestID"); + String serviceInstanceID = httpRequest.getHeader("X-ECOMP-ServiceID"); + if (!StringUtils.isEmpty(requestId)) { + String userId = httpRequest.getHeader("USER_ID"); + String remoteAddr = httpRequest.getRemoteAddr(); + String localAddr = httpRequest.getLocalAddr(); + mdcDataCache.put(requestId, new MdcData(serviceInstanceID, userId, remoteAddr, localAddr, transactionStartTime)); + updateMdc(requestId, serviceInstanceID, userId, remoteAddr, localAddr, null); + } + inHttpRequest(httpRequest); + } + + private void logResponse(HttpServletRequest request, Response proxyResponse) { + String requestId = request.getHeader("X-ECOMP-RequestID"); + if (requestId != null) { + MdcData mdcData = mdcDataCache.getIfPresent(requestId); + if (mdcData != null) { + Long transactionStartTime = mdcData.getTransactionStartTime(); + String transactionRoundTime = Long.toString(System.currentTimeMillis() - transactionStartTime); + updateMdc(requestId, mdcData.getServiceInstanceID(), mdcData.getUserId(), mdcData.getRemoteAddr(), mdcData.getLocalAddr(), transactionRoundTime); + } + } + outHttpResponse(proxyResponse); + MDC.clear(); + } + + private class MdcData { + private String serviceInstanceID; + private String userId; + private String remoteAddr; + private String localAddr; + private Long transactionStartTime; + + MdcData(String serviceInstanceID, String userId, String remoteAddr, String localAddr, Long transactionStartTime) { + this.serviceInstanceID = serviceInstanceID; + this.userId = userId; + this.remoteAddr = remoteAddr; + this.localAddr = localAddr; + this.transactionStartTime = transactionStartTime; + } + + Long getTransactionStartTime() { + return transactionStartTime; + } + + public String getUserId() { + return userId; + } + + String getRemoteAddr() { + return remoteAddr; + } + + String getLocalAddr() { + return localAddr; + } + + String getServiceInstanceID() { + return serviceInstanceID; + } + } + + private void updateMdc(String uuid, String serviceInstanceID, String userId, String remoteAddr, String localAddr, String transactionStartTime) { + MDC.put("uuid", uuid); + MDC.put("serviceInstanceID", serviceInstanceID); + MDC.put("userId", userId); + MDC.put("remoteAddr", remoteAddr); + MDC.put("localAddr", localAddr); + MDC.put("timer", transactionStartTime); + } + + // Extracted for purpose of clear method name, for logback %M parameter + private void inHttpRequest(HttpServletRequest httpRequest) { + log.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol()); + } + + // Extracted for purpose of clear method name, for logback %M parameter + private void outHttpResponse(Response proxyResponse) { + log.info("SC=\"{}\"", proxyResponse.getStatus()); + } + +} diff --git a/src/test/org/onap/sdc/dcae/controller/proxy/DcaeProxyTest.java b/src/test/org/onap/sdc/dcae/controller/proxy/DcaeProxyTest.java new file mode 100644 index 0000000..94cb2c0 --- /dev/null +++ b/src/test/org/onap/sdc/dcae/controller/proxy/DcaeProxyTest.java @@ -0,0 +1,29 @@ +package org.onap.sdc.dcae.controller.proxy; + +import org.junit.Test; +import org.mockito.Mockito; + +import javax.servlet.http.HttpServletRequest; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + + +//TODO headers and cookies test (API) +public class DcaeProxyTest { + + private static final String BEHOST = "https://host.xxx.yyy:8443"; + private DcaeProxy proxy = new DcaeProxy(BEHOST); + private final static HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class); + + + @Test + public void testRewriteUrlWithQueryParams(){ + String requestUrl = "/dcae/dcaeProxy/someBeApi?%20x=1&y=2"; + String expectedUrl = BEHOST + "/dcae/someBeApi?%20x=1&y=2"; + when(servletRequest.getRequestURI()).thenReturn(requestUrl); + String target = proxy.rewriteTarget(servletRequest); + assertTrue(target.equals(expectedUrl)); + } + +} -- cgit 1.2.3-korg