Repository: ambari Updated Branches: refs/heads/trunk f8a5cc1d5 -> 1296ca586
AMBARI-11473 - Fix Tez view to surface underlying errors resulting from failure to communicate with timeline (Hitesh Shah via tbeerbower) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1296ca58 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1296ca58 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1296ca58 Branch: refs/heads/trunk Commit: 1296ca586f83194776c1c80843070e726b9dc340 Parents: f8a5cc1 Author: tbeerbower <tbeerbo...@hortonworks.com> Authored: Fri May 29 16:32:08 2015 -0400 Committer: tbeerbower <tbeerbo...@hortonworks.com> Committed: Fri May 29 16:33:14 2015 -0400 ---------------------------------------------------------------------- contrib/views/tez/pom.xml | 22 ++++- .../apache/ambari/view/tez/ProxyServlet.java | 87 ++++++++++++++++---- 2 files changed, 93 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/1296ca58/contrib/views/tez/pom.xml ---------------------------------------------------------------------- diff --git a/contrib/views/tez/pom.xml b/contrib/views/tez/pom.xml index 8e18702..de0105a 100644 --- a/contrib/views/tez/pom.xml +++ b/contrib/views/tez/pom.xml @@ -23,8 +23,8 @@ </parent> <properties> <ambari.dir>${project.parent.parent.parent.basedir}</ambari.dir> - <tez.view.version>0.6.0-SNAPSHOT</tez.view.version> - <tez.version>0.6.0</tez.version> + <tez.view.version>0.7.0-SNAPSHOT</tez.view.version> + <tez.version>0.7.0</tez.version> </properties> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.ambari.contrib.views</groupId> @@ -157,6 +157,12 @@ </dependency> <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-core</artifactId> + <version>1.8</version> + </dependency> + + <dependency> <groupId>org.apache.ambari</groupId> <artifactId>ambari-views</artifactId> <version>${ambari.version}</version> @@ -174,5 +180,17 @@ <artifactId>guice</artifactId> </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.5</version> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.4</version> + </dependency> + </dependencies> </project> http://git-wip-us.apache.org/repos/asf/ambari/blob/1296ca58/contrib/views/tez/src/main/java/org/apache/ambari/view/tez/ProxyServlet.java ---------------------------------------------------------------------- diff --git a/contrib/views/tez/src/main/java/org/apache/ambari/view/tez/ProxyServlet.java b/contrib/views/tez/src/main/java/org/apache/ambari/view/tez/ProxyServlet.java index 0fdd47a..edc647d 100644 --- a/contrib/views/tez/src/main/java/org/apache/ambari/view/tez/ProxyServlet.java +++ b/contrib/views/tez/src/main/java/org/apache/ambari/view/tez/ProxyServlet.java @@ -18,11 +18,14 @@ package org.apache.ambari.view.tez; +import org.apache.ambari.view.URLConnectionProvider; import org.apache.ambari.view.ViewContext; -import org.apache.ambari.view.HttpImpersonator; -import org.apache.ambari.view.ImpersonatorSetting; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; @@ -30,26 +33,33 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import java.net.HttpURLConnection; import java.net.URLDecoder; +import java.util.Collections; +import java.util.Map; /** * Simple servlet for proxying requests with doAs impersonation. */ public class ProxyServlet extends HttpServlet { - private ViewContext viewContext; - private HttpImpersonator impersonator; - private ImpersonatorSetting impersonatorSetting; + private static final Logger LOG = LoggerFactory.getLogger(ProxyServlet.class); + + private URLConnectionProvider urlConnectionProvider; + private final static String nullData = null; + private final static Map<String, String> emptyHeaders = Collections.EMPTY_MAP; @Override public void init(ServletConfig config) throws ServletException { super.init(config); ServletContext context = config.getServletContext(); - viewContext = (ViewContext) context.getAttribute(ViewContext.CONTEXT_ATTRIBUTE); - - this.impersonator = viewContext.getHttpImpersonator(); - this.impersonatorSetting = viewContext.getImpersonatorSetting(); + ViewContext viewContext = (ViewContext) context.getAttribute(ViewContext.CONTEXT_ATTRIBUTE); + this.urlConnectionProvider = viewContext.getURLConnectionProvider(); } @Override @@ -58,14 +68,63 @@ public class ProxyServlet extends HttpServlet { response.setContentType(request.getContentType()); - // Getting the result is super simply by using the impersonator and the default values in the factory. - String result = this.impersonator.requestURL(urlToRead, "GET", this.impersonatorSetting); - Boolean notFound = result == "" || result.indexOf("\"exception\":\"NotFoundException\"") != -1; + if (LOG.isDebugEnabled()) { + LOG.debug("Requesting data from ATS, url=" + urlToRead); + } + + InputStream resultInputStream; + String result = ""; + // When in doubt, assume error + int responseCode = Status.INTERNAL_SERVER_ERROR.getStatusCode(); + HttpURLConnection connection; + try { + // Use nullData as null string and null inputstream cannot be disambiguated + // URL Stream Provider will automatically inject the doAs param with the current + // user's info + connection = urlConnectionProvider.getConnectionAsCurrent(urlToRead, + HttpMethod.GET, nullData, emptyHeaders); + responseCode = connection.getResponseCode(); - response.setStatus(notFound ? HttpServletResponse.SC_NOT_FOUND : HttpServletResponse.SC_OK); + if (LOG.isDebugEnabled()) { + LOG.debug("Received response from ATS, url=" + urlToRead + + ", responseCode=" + responseCode); + } + if (responseCode >= Response.Status.BAD_REQUEST.getStatusCode()) { + resultInputStream = connection.getErrorStream(); + } else { + resultInputStream = connection.getInputStream(); + } + + result = IOUtils.toString(resultInputStream); + if (LOG.isDebugEnabled()) { + LOG.debug("Received response from ATS, url=" + urlToRead + + ", responseCode=" + responseCode + + ", responseBodyLen=" + result.length()); + } + + } catch (IOException e) { + // We might kill the ambari server by logging this error every time a call fails + if (LOG.isDebugEnabled()) { + LOG.warn("Failed to retrieve data from ATS, url=" + urlToRead, e); + } + responseCode = Status.INTERNAL_SERVER_ERROR.getStatusCode(); + result = e.toString(); + } catch (Exception e) { + LOG.warn("Unknown Exception: Failed to retrieve data from ATS, url=" + urlToRead, e); + responseCode = Status.INTERNAL_SERVER_ERROR.getStatusCode(); + result = e.toString(); + } finally { + // not disconnecting http conn as it might be cached/re-used internally + // in the UrlStreamProvider + } + + response.setStatus(responseCode); PrintWriter writer = response.getWriter(); - writer.print(result); + if (result != null) { + writer.print(result); + } } + }