/** * 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 static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.never; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ha.HAServiceProtocol; import org.apache.hadoop.ha.HAServiceStatus; import org.apache.hadoop.ha.HAServiceTarget; import org.apache.hadoop.yarn.client.cli.RMAdminCLI; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.server.api.ResourceManagerAdministrationProtocol; import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshAdminAclsRequest; import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshNodesRequest; import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshQueuesRequest; import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshServiceAclsRequest; import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshSuperUserGroupsConfigurationRequest; import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshUserToGroupsMappingsRequest; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentMatcher; public class TestRMAdminCLI { private ResourceManagerAdministrationProtocol admin; private HAServiceProtocol haadmin; private RMAdminCLI rmAdminCLI; private RMAdminCLI rmAdminCLIWithHAEnabled; @Before public void configure() throws IOException { admin = mock(ResourceManagerAdministrationProtocol.class); haadmin = mock(HAServiceProtocol.class); when(haadmin.getServiceStatus()).thenReturn(new HAServiceStatus( HAServiceProtocol.HAServiceState.INITIALIZING)); final HAServiceTarget haServiceTarget = mock(HAServiceTarget.class); when(haServiceTarget.getProxy(any(Configuration.class), anyInt())) .thenReturn(haadmin); rmAdminCLI = new RMAdminCLI(new Configuration()) { @Override protected ResourceManagerAdministrationProtocol createAdminProtocol() throws IOException { return admin; } @Override protected HAServiceTarget resolveTarget(String rmId) { return haServiceTarget; } }; YarnConfiguration conf = new YarnConfiguration(); conf.setBoolean(YarnConfiguration.RM_HA_ENABLED, true); rmAdminCLIWithHAEnabled = new RMAdminCLI(conf) { @Override protected ResourceManagerAdministrationProtocol createAdminProtocol() throws IOException { return admin; } @Override protected HAServiceTarget resolveTarget(String rmId) { return haServiceTarget; } }; } @Test(timeout=500) public void testRefreshQueues() throws Exception { String[] args = { "-refreshQueues" }; assertEquals(0, rmAdminCLI.run(args)); verify(admin).refreshQueues(any(RefreshQueuesRequest.class)); } @Test(timeout=500) public void testRefreshUserToGroupsMappings() throws Exception { String[] args = { "-refreshUserToGroupsMappings" }; assertEquals(0, rmAdminCLI.run(args)); verify(admin).refreshUserToGroupsMappings( any(RefreshUserToGroupsMappingsRequest.class)); } @Test(timeout=500) public void testRefreshSuperUserGroupsConfiguration() throws Exception { String[] args = { "-refreshSuperUserGroupsConfiguration" }; assertEquals(0, rmAdminCLI.run(args)); verify(admin).refreshSuperUserGroupsConfiguration( any(RefreshSuperUserGroupsConfigurationRequest.class)); } @Test(timeout=500) public void testRefreshAdminAcls() throws Exception { String[] args = { "-refreshAdminAcls" }; assertEquals(0, rmAdminCLI.run(args)); verify(admin).refreshAdminAcls(any(RefreshAdminAclsRequest.class)); } @Test(timeout=500) public void testRefreshServiceAcl() throws Exception { String[] args = { "-refreshServiceAcl" }; assertEquals(0, rmAdminCLI.run(args)); verify(admin).refreshServiceAcls(any(RefreshServiceAclsRequest.class)); } @Test(timeout=500) public void testRefreshNodes() throws Exception { String[] args = { "-refreshNodes" }; assertEquals(0, rmAdminCLI.run(args)); verify(admin).refreshNodes(any(RefreshNodesRequest.class)); } @Test(timeout=500) public void testGetGroups() throws Exception { when(admin.getGroupsForUser(eq("admin"))).thenReturn( new String[] {"group1", "group2"}); PrintStream origOut = System.out; PrintStream out = mock(PrintStream.class); System.setOut(out); try { String[] args = { "-getGroups", "admin" }; assertEquals(0, rmAdminCLI.run(args)); verify(admin).getGroupsForUser(eq("admin")); verify(out).println(argThat(new ArgumentMatcher<StringBuilder>() { @Override public boolean matches(Object argument) { return ("" + argument).equals("admin : group1 group2"); } })); } finally { System.setOut(origOut); } } @Test(timeout = 500) public void testTransitionToActive() throws Exception { String[] args = {"-transitionToActive", "rm1"}; // RM HA is disabled. // transitionToActive should not be executed assertEquals(-1, rmAdminCLI.run(args)); verify(haadmin, never()).transitionToActive( any(HAServiceProtocol.StateChangeRequestInfo.class)); // Now RM HA is enabled. // transitionToActive should be executed assertEquals(0, rmAdminCLIWithHAEnabled.run(args)); verify(haadmin).transitionToActive( any(HAServiceProtocol.StateChangeRequestInfo.class)); } @Test(timeout = 500) public void testTransitionToStandby() throws Exception { String[] args = {"-transitionToStandby", "rm1"}; // RM HA is disabled. // transitionToStandby should not be executed assertEquals(-1, rmAdminCLI.run(args)); verify(haadmin, never()).transitionToStandby( any(HAServiceProtocol.StateChangeRequestInfo.class)); // Now RM HA is enabled. // transitionToActive should be executed assertEquals(0, rmAdminCLIWithHAEnabled.run(args)); verify(haadmin).transitionToStandby( any(HAServiceProtocol.StateChangeRequestInfo.class)); } @Test(timeout = 500) public void testGetServiceState() throws Exception { String[] args = {"-getServiceState", "rm1"}; // RM HA is disabled. // getServiceState should not be executed assertEquals(-1, rmAdminCLI.run(args)); verify(haadmin, never()).getServiceStatus(); // Now RM HA is enabled. // getServiceState should be executed assertEquals(0, rmAdminCLIWithHAEnabled.run(args)); verify(haadmin).getServiceStatus(); } @Test(timeout = 500) public void testCheckHealth() throws Exception { String[] args = {"-checkHealth", "rm1"}; // RM HA is disabled. // getServiceState should not be executed assertEquals(-1, rmAdminCLI.run(args)); verify(haadmin, never()).monitorHealth(); // Now RM HA is enabled. // getServiceState should be executed assertEquals(0, rmAdminCLIWithHAEnabled.run(args)); verify(haadmin).monitorHealth(); } /** * Test printing of help messages */ @Test(timeout=500) public void testHelp() throws Exception { PrintStream oldOutPrintStream = System.out; PrintStream oldErrPrintStream = System.err; ByteArrayOutputStream dataOut = new ByteArrayOutputStream(); ByteArrayOutputStream dataErr = new ByteArrayOutputStream(); System.setOut(new PrintStream(dataOut)); System.setErr(new PrintStream(dataErr)); try { String[] args = { "-help" }; assertEquals(0, rmAdminCLI.run(args)); oldOutPrintStream.println(dataOut); assertTrue(dataOut .toString() .contains( "rmadmin is the command to execute YARN administrative commands.")); assertTrue(dataOut .toString() .contains( "yarn rmadmin [-refreshQueues] [-refreshNodes] [-refreshSuper" + "UserGroupsConfiguration] [-refreshUserToGroupsMappings] " + "[-refreshAdminAcls] [-refreshServiceAcl] [-getGroup" + " [username]] [-help [cmd]]")); assertTrue(dataOut .toString() .contains( "-refreshQueues: Reload the queues' acls, states and scheduler " + "specific properties.")); assertTrue(dataOut .toString() .contains( "-refreshNodes: Refresh the hosts information at the " + "ResourceManager.")); assertTrue(dataOut.toString().contains( "-refreshUserToGroupsMappings: Refresh user-to-groups mappings")); assertTrue(dataOut .toString() .contains( "-refreshSuperUserGroupsConfiguration: Refresh superuser proxy" + " groups mappings")); assertTrue(dataOut .toString() .contains( "-refreshAdminAcls: Refresh acls for administration of " + "ResourceManager")); assertTrue(dataOut .toString() .contains( "-refreshServiceAcl: Reload the service-level authorization" + " policy file")); assertTrue(dataOut .toString() .contains( "-help [cmd]: Displays help for the given command or all " + "commands if none")); testError(new String[] { "-help", "-refreshQueues" }, "Usage: yarn rmadmin [-refreshQueues]", dataErr, 0); testError(new String[] { "-help", "-refreshNodes" }, "Usage: yarn rmadmin [-refreshNodes]", dataErr, 0); testError(new String[] { "-help", "-refreshUserToGroupsMappings" }, "Usage: yarn rmadmin [-refreshUserToGroupsMappings]", dataErr, 0); testError( new String[] { "-help", "-refreshSuperUserGroupsConfiguration" }, "Usage: yarn rmadmin [-refreshSuperUserGroupsConfiguration]", dataErr, 0); testError(new String[] { "-help", "-refreshAdminAcls" }, "Usage: yarn rmadmin [-refreshAdminAcls]", dataErr, 0); testError(new String[] { "-help", "-refreshServiceAcl" }, "Usage: yarn rmadmin [-refreshServiceAcl]", dataErr, 0); testError(new String[] { "-help", "-getGroups" }, "Usage: yarn rmadmin [-getGroups [username]]", dataErr, 0); testError(new String[] { "-help", "-transitionToActive" }, "Usage: yarn rmadmin [-transitionToActive <serviceId>]", dataErr, 0); testError(new String[] { "-help", "-transitionToStandby" }, "Usage: yarn rmadmin [-transitionToStandby <serviceId>]", dataErr, 0); testError(new String[] { "-help", "-getServiceState" }, "Usage: yarn rmadmin [-getServiceState <serviceId>]", dataErr, 0); testError(new String[] { "-help", "-checkHealth" }, "Usage: yarn rmadmin [-checkHealth <serviceId>]", dataErr, 0); testError(new String[] { "-help", "-failover" }, "Usage: yarn rmadmin " + "[-failover [--forcefence] [--forceactive] " + "<serviceId> <serviceId>]", dataErr, 0); testError(new String[] { "-help", "-badParameter" }, "Usage: yarn rmadmin", dataErr, 0); testError(new String[] { "-badParameter" }, "badParameter: Unknown command", dataErr, -1); // Test -help when RM HA is enabled assertEquals(0, rmAdminCLIWithHAEnabled.run(args)); oldOutPrintStream.println(dataOut); assertTrue(dataOut .toString() .contains( "yarn rmadmin [-refreshQueues] [-refreshNodes] [-refreshSuper" + "UserGroupsConfiguration] [-refreshUserToGroupsMappings] " + "[-refreshAdminAcls] [-refreshServiceAcl] [-getGroup" + " [username]] [-help [cmd]] [-transitionToActive <serviceId>]" + " [-transitionToStandby <serviceId>] [-failover [--forcefence]" + " [--forceactive] <serviceId> <serviceId>] " + "[-getServiceState <serviceId>] [-checkHealth <serviceId>]")); } finally { System.setOut(oldOutPrintStream); System.setErr(oldErrPrintStream); } } @Test(timeout=500) public void testException() throws Exception { PrintStream oldErrPrintStream = System.err; ByteArrayOutputStream dataErr = new ByteArrayOutputStream(); System.setErr(new PrintStream(dataErr)); try { when(admin.refreshQueues(any(RefreshQueuesRequest.class))) .thenThrow(new IOException("test exception")); String[] args = { "-refreshQueues" }; assertEquals(-1, rmAdminCLI.run(args)); verify(admin).refreshQueues(any(RefreshQueuesRequest.class)); assertTrue(dataErr.toString().contains("refreshQueues: test exception")); } finally { System.setErr(oldErrPrintStream); } } private void testError(String[] args, String template, ByteArrayOutputStream data, int resultCode) throws Exception { assertEquals(resultCode, rmAdminCLI.run(args)); assertTrue(data.toString().contains(template)); data.reset(); } }