Browse Source

YARN-11584. Safely fail on leaf queue with empty name (#6148)

Brian Goerlitz 1 year ago
parent
commit
4c04a6768c

+ 5 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/QueuePath.java

@@ -96,6 +96,11 @@ public class QueuePath implements Iterable<String> {
    * @return true if there is at least one empty part of the path
    */
   public boolean hasEmptyPart() {
+    // iterator will not contain an empty leaf queue, so check directly
+    if (leaf.isEmpty()) {
+      return true;
+    }
+
     for (String part : this) {
       if (part.isEmpty()) {
         return true;

+ 38 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestCapacitySchedulerAutoQueueCreation.java

@@ -109,6 +109,8 @@ public class TestCapacitySchedulerAutoQueueCreation
   private static final Logger LOG = LoggerFactory.getLogger(
       TestCapacitySchedulerAutoQueueCreation.class);
 
+  private static final String SPECIFIED_QUEUE_MAPPING = "%specified";
+
   private static final String CURRENT_USER_MAPPING = "%user";
 
   private static final Resource TEMPLATE_MAX_RES = Resource.newInstance(16 *
@@ -1054,4 +1056,40 @@ public class TestCapacitySchedulerAutoQueueCreation
       }
     }
   }
+
+  @Test(timeout = 10000)
+  public void testAutoCreateLeafQueueFailsWithSpecifiedEmptyStringLeafQueue()
+          throws Exception {
+
+    final String invalidQueue = "";
+
+    MockRM newMockRM = setupSchedulerInstance();
+    CapacityScheduler newCS =
+            (CapacityScheduler) newMockRM.getResourceScheduler();
+
+    //queue mapping to place app in queue specified by user
+    setupQueueMapping(newCS, "app_user", "root.c", SPECIFIED_QUEUE_MAPPING);
+    newCS.updatePlacementRules();
+
+    try {
+      //submitting to root.c. should fail WITHOUT crashing the RM
+      submitApp(newCS, "app_user", invalidQueue, "root.c");
+
+      RMContext rmContext = mock(RMContext.class);
+      when(rmContext.getDispatcher()).thenReturn(dispatcher);
+      newCS.setRMContext(rmContext);
+
+      ApplicationId appId = BuilderUtils.newApplicationId(1, 1);
+      SchedulerEvent addAppEvent = new AppAddedSchedulerEvent(
+              appId, "root.c." + invalidQueue, "app_user");
+      newCS.handle(addAppEvent);
+
+      RMAppEvent event = new RMAppEvent(appId, RMAppEventType.APP_REJECTED,
+              "error");
+      dispatcher.spyOnNextEvent(event, 10000);
+    } finally {
+      ((CapacityScheduler) newMockRM.getResourceScheduler()).stop();
+      newMockRM.stop();
+    }
+  }
 }

+ 2 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestQueuePath.java

@@ -48,9 +48,11 @@ public class TestQueuePath {
   @Test
   public void testEmptyPart() {
     QueuePath queuePathWithEmptyPart = new QueuePath("root..level_2");
+    QueuePath queuePathWithEmptyLeaf = new QueuePath("root.level_1.");
     QueuePath queuePathWithoutEmptyPart = new QueuePath(TEST_QUEUE);
 
     Assert.assertTrue(queuePathWithEmptyPart.hasEmptyPart());
+    Assert.assertTrue(queuePathWithEmptyLeaf.hasEmptyPart());
     Assert.assertFalse(queuePathWithoutEmptyPart.hasEmptyPart());
   }