diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/ClientRMProxy.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/ClientRMProxy.java deleted file mode 100644 index 06bbc35..0000000 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/ClientRMProxy.java +++ /dev/null @@ -1,123 +0,0 @@ -/** -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you 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.apache.hadoop.yarn.client; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.security.SecurityUtil; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.security.token.Token; -import org.apache.hadoop.security.token.TokenIdentifier; -import org.apache.hadoop.yarn.api.ApplicationClientProtocol; -import org.apache.hadoop.yarn.api.ApplicationMasterProtocol; -import org.apache.hadoop.yarn.conf.YarnConfiguration; -import org.apache.hadoop.yarn.security.AMRMTokenIdentifier; -import org.apache.hadoop.yarn.server.api.ResourceManagerAdministrationProtocol; - -import com.google.common.base.Preconditions; - -public class ClientRMProxy extends RMProxy { - private static final Log LOG = LogFactory.getLog(ClientRMProxy.class); - - private interface ClientRMProtocols extends ApplicationClientProtocol, - ApplicationMasterProtocol, ResourceManagerAdministrationProtocol { - // Add nothing - } - - static { - INSTANCE = new ClientRMProxy(); - } - - private ClientRMProxy(){ - super(); - } - - /** - * Create a proxy to the ResourceManager for the specified protocol. - * @param configuration Configuration with all the required information. - * @param protocol Client protocol for which proxy is being requested. - * @param Type of proxy. - * @return Proxy to the ResourceManager for the specified client protocol. - * @throws IOException - */ - public static T createRMProxy(final Configuration configuration, - final Class protocol) throws IOException { - // This method exists only to initiate this class' static INSTANCE. TODO: - // FIX if possible - return RMProxy.createRMProxy(configuration, protocol); - } - - private static void setupTokens(InetSocketAddress resourceManagerAddress) - throws IOException { - // It is assumed for now that the only AMRMToken in AM's UGI is for this - // cluster/RM. TODO: Fix later when we have some kind of cluster-ID as - // default service-address, see YARN-986. - for (Token token : UserGroupInformation - .getCurrentUser().getTokens()) { - if (token.getKind().equals(AMRMTokenIdentifier.KIND_NAME)) { - // This token needs to be directly provided to the AMs, so set the - // appropriate service-name. We'll need more infrastructure when we - // need to set it in HA case. - SecurityUtil.setTokenService(token, resourceManagerAddress); - } - } - } - - @InterfaceAudience.Private - @Override - protected InetSocketAddress getRMAddress(YarnConfiguration conf, - Class protocol) throws IOException { - if (protocol == ApplicationClientProtocol.class) { - return conf.getSocketAddr(YarnConfiguration.RM_ADDRESS, - YarnConfiguration.DEFAULT_RM_ADDRESS, - YarnConfiguration.DEFAULT_RM_PORT); - } else if (protocol == ResourceManagerAdministrationProtocol.class) { - return conf.getSocketAddr( - YarnConfiguration.RM_ADMIN_ADDRESS, - YarnConfiguration.DEFAULT_RM_ADMIN_ADDRESS, - YarnConfiguration.DEFAULT_RM_ADMIN_PORT); - } else if (protocol == ApplicationMasterProtocol.class) { - InetSocketAddress serviceAddr = - conf.getSocketAddr(YarnConfiguration.RM_SCHEDULER_ADDRESS, - YarnConfiguration.DEFAULT_RM_SCHEDULER_ADDRESS, - YarnConfiguration.DEFAULT_RM_SCHEDULER_PORT); - setupTokens(serviceAddr); - return serviceAddr; - } else { - String message = "Unsupported protocol found when creating the proxy " + - "connection to ResourceManager: " + - ((protocol != null) ? protocol.getClass().getName() : "null"); - LOG.error(message); - throw new IllegalStateException(message); - } - } - - @InterfaceAudience.Private - @Override - protected void checkAllowedProtocols(Class protocol) { - Preconditions.checkArgument( - protocol.isAssignableFrom(ClientRMProtocols.class), - "RM does not support this client protocol"); - } -} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java index 8545a1a..5dedab1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java @@ -29,12 +29,17 @@ import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ha.HAServiceProtocol; +import org.apache.hadoop.service.Service.STATE; +import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.client.api.YarnClient; import org.apache.hadoop.yarn.conf.HAUtil; import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.server.MiniYARNCluster; import org.apache.hadoop.yarn.server.resourcemanager.AdminService; +import org.apache.hadoop.yarn.server.webproxy.AppReportFetcher; +import org.apache.hadoop.yarn.server.webproxy.WebAppProxyServer; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -50,9 +55,13 @@ private static final HAServiceProtocol.StateChangeRequestInfo req = new HAServiceProtocol.StateChangeRequestInfo( HAServiceProtocol.RequestSource.REQUEST_BY_USER_FORCED); + private static final ApplicationId appId = + ApplicationId.newInstance(System.currentTimeMillis(), 0); private static Configuration conf; private static MiniYARNCluster cluster; + private static WebAppProxyServer webAppProxyServer = null; + private static final int maxWaitTimes = 3; private static void setConfForRM(String rmId, String prefix, String value) { conf.set(HAUtil.addSuffix(prefix, rmId), value); @@ -91,23 +100,43 @@ public static void setup() throws IOException { conf.setLong(YarnConfiguration.CLIENT_FAILOVER_SLEEPTIME_MAX_MS, 1000L); conf.setBoolean(YarnConfiguration.YARN_MINICLUSTER_FIXED_PORTS, true); conf.setBoolean(YarnConfiguration.YARN_MINICLUSTER_USE_RPC, true); - + conf.set(YarnConfiguration.PROXY_ADDRESS, "0.0.0.0:9099"); cluster = new MiniYARNCluster(TestRMFailover.class.getName(), 2, 1, 1, 1); cluster.init(conf); cluster.start(); + int numTries = maxWaitTimes; + while ((cluster.getServiceState() != STATE.STARTED) && (numTries > 0) ) { + numTries --; + try { + Thread.sleep(500); + } catch (Exception e) { + // Do nothing + } + } + assertEquals(STATE.STARTED, cluster.getServiceState()); + + webAppProxyServer = new WebAppProxyServer(); + webAppProxyServer.init(conf); + cluster.getResourceManager(0).getRMContext().getRMAdminService() .transitionToActive(req); assertFalse("RM never turned active", -1 == cluster.getActiveRMIndex()); + + //Start webAppProxyServer + assertEquals(STATE.INITED, webAppProxyServer.getServiceState()); + webAppProxyServer.start(); + assertEquals(STATE.STARTED, webAppProxyServer.getServiceState()); } @AfterClass public static void teardown() { cluster.stop(); + webAppProxyServer.stop(); } private void verifyClientConnection() { - int numRetries = 3; + int numRetries = maxWaitTimes; while(numRetries-- > 0) { Configuration conf = new YarnConfiguration(TestRMFailover.conf); YarnClient client = YarnClient.createYarnClient(); @@ -125,12 +154,40 @@ private void verifyClientConnection() { fail("Client couldn't connect to the Active RM"); } + private void verifyWebAppProxy(ApplicationId appId) { + // give the fake ApplicationId. + // We should receive the ApplicationNotFoundException from the active RM + // which means that it connect to current active RM successfully + int numRetries = maxWaitTimes; + boolean getExpectException = false; + while (numRetries-- > 0) { + AppReportFetcher fetcher = + webAppProxyServer.getWebAppProxy().getAppReportFetcher(); + try { + fetcher.getApplicationReport(appId); + return; + } catch (Exception e) { + LOG.error(e); + if (e instanceof ApplicationNotFoundException) { + if (e.getMessage().contains( + "Application with id '" + appId + "' doesn't exist in RM.")) { + getExpectException = true; + } + } + } + } + if (! getExpectException) { + fail("WebAppProxy couldn't connect to the Active RM"); + } + } + @Test public void testExplicitFailover() throws YarnException, InterruptedException, IOException { assertTrue("NMs failed to connect to the RM", cluster.waitForNodeManagersToConnect(5000)); verifyClientConnection(); + verifyWebAppProxy(appId); // Failover to the second RM getRMAdminService(0).transitionToStandby(req); @@ -141,6 +198,7 @@ public void testExplicitFailover() assertTrue("NMs failed to connect to the RM", cluster.waitForNodeManagersToConnect(5000)); verifyClientConnection(); + verifyWebAppProxy(appId); // Failover back to the first RM getRMAdminService(1).transitionToStandby(req); @@ -151,5 +209,6 @@ public void testExplicitFailover() assertTrue("NMs failed to connect to the RM", cluster.waitForNodeManagersToConnect(5000)); verifyClientConnection(); + verifyWebAppProxy(appId); } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/ClientRMProxy.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/ClientRMProxy.java new file mode 100644 index 0000000..06bbc35 --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/ClientRMProxy.java @@ -0,0 +1,123 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you 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.apache.hadoop.yarn.client; + +import java.io.IOException; +import java.net.InetSocketAddress; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.security.SecurityUtil; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.token.Token; +import org.apache.hadoop.security.token.TokenIdentifier; +import org.apache.hadoop.yarn.api.ApplicationClientProtocol; +import org.apache.hadoop.yarn.api.ApplicationMasterProtocol; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.security.AMRMTokenIdentifier; +import org.apache.hadoop.yarn.server.api.ResourceManagerAdministrationProtocol; + +import com.google.common.base.Preconditions; + +public class ClientRMProxy extends RMProxy { + private static final Log LOG = LogFactory.getLog(ClientRMProxy.class); + + private interface ClientRMProtocols extends ApplicationClientProtocol, + ApplicationMasterProtocol, ResourceManagerAdministrationProtocol { + // Add nothing + } + + static { + INSTANCE = new ClientRMProxy(); + } + + private ClientRMProxy(){ + super(); + } + + /** + * Create a proxy to the ResourceManager for the specified protocol. + * @param configuration Configuration with all the required information. + * @param protocol Client protocol for which proxy is being requested. + * @param Type of proxy. + * @return Proxy to the ResourceManager for the specified client protocol. + * @throws IOException + */ + public static T createRMProxy(final Configuration configuration, + final Class protocol) throws IOException { + // This method exists only to initiate this class' static INSTANCE. TODO: + // FIX if possible + return RMProxy.createRMProxy(configuration, protocol); + } + + private static void setupTokens(InetSocketAddress resourceManagerAddress) + throws IOException { + // It is assumed for now that the only AMRMToken in AM's UGI is for this + // cluster/RM. TODO: Fix later when we have some kind of cluster-ID as + // default service-address, see YARN-986. + for (Token token : UserGroupInformation + .getCurrentUser().getTokens()) { + if (token.getKind().equals(AMRMTokenIdentifier.KIND_NAME)) { + // This token needs to be directly provided to the AMs, so set the + // appropriate service-name. We'll need more infrastructure when we + // need to set it in HA case. + SecurityUtil.setTokenService(token, resourceManagerAddress); + } + } + } + + @InterfaceAudience.Private + @Override + protected InetSocketAddress getRMAddress(YarnConfiguration conf, + Class protocol) throws IOException { + if (protocol == ApplicationClientProtocol.class) { + return conf.getSocketAddr(YarnConfiguration.RM_ADDRESS, + YarnConfiguration.DEFAULT_RM_ADDRESS, + YarnConfiguration.DEFAULT_RM_PORT); + } else if (protocol == ResourceManagerAdministrationProtocol.class) { + return conf.getSocketAddr( + YarnConfiguration.RM_ADMIN_ADDRESS, + YarnConfiguration.DEFAULT_RM_ADMIN_ADDRESS, + YarnConfiguration.DEFAULT_RM_ADMIN_PORT); + } else if (protocol == ApplicationMasterProtocol.class) { + InetSocketAddress serviceAddr = + conf.getSocketAddr(YarnConfiguration.RM_SCHEDULER_ADDRESS, + YarnConfiguration.DEFAULT_RM_SCHEDULER_ADDRESS, + YarnConfiguration.DEFAULT_RM_SCHEDULER_PORT); + setupTokens(serviceAddr); + return serviceAddr; + } else { + String message = "Unsupported protocol found when creating the proxy " + + "connection to ResourceManager: " + + ((protocol != null) ? protocol.getClass().getName() : "null"); + LOG.error(message); + throw new IllegalStateException(message); + } + } + + @InterfaceAudience.Private + @Override + protected void checkAllowedProtocols(Class protocol) { + Preconditions.checkArgument( + protocol.isAssignableFrom(ClientRMProtocols.class), + "RM does not support this client protocol"); + } +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java index e442077..a1c136e 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java @@ -159,6 +159,7 @@ private WebApp webApp; protected ResourceTrackerService resourceTracker; private boolean recoveryEnabled; + private String webAppProxyAddress; /** End of Active services */ @@ -196,6 +197,7 @@ protected void serviceInit(Configuration conf) throws Exception { HAUtil.verifyAndSetConfiguration(conf); } createAndInitActiveServices(); + webAppProxyAddress = WebAppUtils.getRMWebAppURLWithoutScheme(conf); super.serviceInit(conf); } @@ -482,26 +484,17 @@ protected void serviceStart() throws Exception { } } - startWepApp(); try { rmDTSecretManager.startThreads(); } catch(IOException ie) { throw new YarnRuntimeException("Failed to start secret manager threads", ie); } - if (getConfig().getBoolean(YarnConfiguration.IS_MINI_YARN_CLUSTER, false)) { - int port = webApp.port(); - WebAppUtils.setRMWebAppPort(conf, port); - } - super.serviceStart(); } @Override protected void serviceStop() throws Exception { - if (webApp != null) { - webApp.stop(); - } if (rmDTSecretManager != null) { rmDTSecretManager.stopThreads(); } @@ -820,11 +813,16 @@ protected void startWepApp() { YarnConfiguration.RM_WEBAPP_SPNEGO_USER_NAME_KEY) .withHttpSpnegoKeytabKey( YarnConfiguration.RM_WEBAPP_SPNEGO_KEYTAB_FILE_KEY) - .at(WebAppUtils.getRMWebAppURLWithoutScheme(conf)); + .at(webAppProxyAddress); String proxyHostAndPort = WebAppUtils.getProxyHostAndPort(conf); if(WebAppUtils.getResolvedRMWebAppURLWithoutScheme(conf). equals(proxyHostAndPort)) { - AppReportFetcher fetcher = new AppReportFetcher(conf, getClientRMService()); + AppReportFetcher fetcher; + if (HAUtil.isHAEnabled(conf)) { + fetcher = new AppReportFetcher(conf); + } else { + fetcher = new AppReportFetcher(conf, getClientRMService()); + } builder.withServlet(ProxyUriUtils.PROXY_SERVLET_NAME, ProxyUriUtils.PROXY_PATH_SPEC, WebAppProxyServlet.class); builder.withAttribute(WebAppProxy.FETCHER_ATTRIBUTE, fetcher); @@ -915,13 +913,18 @@ protected void serviceStart() throws Exception { } catch(IOException ie) { throw new YarnRuntimeException("Failed to login", ie); } - if (this.rmContext.isHAEnabled()) { transitionToStandby(true); } else { transitionToActive(); } + startWepApp(); + + if (getConfig().getBoolean(YarnConfiguration.IS_MINI_YARN_CLUSTER, false)) { + int port = webApp.port(); + WebAppUtils.setRMWebAppPort(conf, port); + } super.serviceStart(); } @@ -932,6 +935,9 @@ protected void doSecureLogin() throws IOException { @Override protected void serviceStop() throws Exception { + if (webApp != null) { + webApp.stop(); + } super.serviceStop(); transitionToStandby(false); rmContext.setHAServiceState(HAServiceState.STOPPING); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java index 077783f..6b55ad1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java @@ -19,8 +19,6 @@ package org.apache.hadoop.yarn.server.webproxy; import java.io.IOException; -import java.net.InetSocketAddress; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; @@ -29,11 +27,11 @@ import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationReport; -import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.client.ClientRMProxy; import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; import org.apache.hadoop.yarn.factories.RecordFactory; import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; -import org.apache.hadoop.yarn.ipc.YarnRPC; /** * This class abstracts away how ApplicationReports are fetched. @@ -50,16 +48,12 @@ */ public AppReportFetcher(Configuration conf) { this.conf = conf; - YarnRPC rpc = YarnRPC.create(this.conf); - InetSocketAddress rmAddress = conf.getSocketAddr( - YarnConfiguration.RM_ADDRESS, - YarnConfiguration.DEFAULT_RM_ADDRESS, - YarnConfiguration.DEFAULT_RM_PORT); - LOG.info("Connecting to ResourceManager at " + rmAddress); - applicationsManager = - (ApplicationClientProtocol) rpc.getProxy(ApplicationClientProtocol.class, - rmAddress, this.conf); - LOG.info("Connected to ResourceManager at " + rmAddress); + try { + applicationsManager = ClientRMProxy.createRMProxy(conf, + ApplicationClientProtocol.class); + } catch (IOException e) { + throw new YarnRuntimeException(e); + } } /** diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxy.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxy.java index 2fbb0b8..36d2965 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxy.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxy.java @@ -133,4 +133,9 @@ public void join() { String getBindAddress() { return bindAddress + ":" + port; } + + @VisibleForTesting + public AppReportFetcher getAppReportFetcher() { + return this.fetcher; + } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServer.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServer.java index c8474a5..7c3146d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServer.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServer.java @@ -31,6 +31,8 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; +import com.google.common.annotations.VisibleForTesting; + /** * ProxyServer will sit in between the end user and AppMaster * web interfaces. @@ -101,4 +103,9 @@ protected static WebAppProxyServer startServer(Configuration configuration) return proxy; } + @VisibleForTesting + public WebAppProxy getWebAppProxy() { + return this.proxy; + } + }