diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceUtils.java index c9cc27b3119..c4c69493c7f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/util/resource/ResourceUtils.java @@ -62,6 +62,10 @@ private static final Pattern RESOURCE_REQUEST_VALUE_PATTERN = Pattern.compile("^([0-9]+) ?([a-zA-Z]*)$"); + private static final Pattern RESOURCE_NAME_PATTERN = Pattern.compile( + "^(((\\p{Alnum}([\\p{Alnum}-]*\\p{Alnum})?\\.)*" + + "\\p{Alnum}([\\p{Alnum}-]*\\p{Alnum})?)/)?\\p{Alpha}([\\w.-]*)$"); + private static volatile boolean initializedResources = false; private static final Map RESOURCE_NAME_TO_INDEX = new ConcurrentHashMap(); @@ -209,6 +213,18 @@ private static void setMaximumAllocationForMandatoryResources( } @VisibleForTesting + static void validateNameOfResourceNameAndThorwException(String resourceName) + throws YarnRuntimeException { + Matcher matcher = RESOURCE_NAME_PATTERN.matcher(resourceName); + if (!matcher.matches()) { + String message = + "Failed to match resourceName=" + resourceName + " to regex pattern:" + + RESOURCE_NAME_PATTERN.pattern() + ", please double check."; + throw new YarnRuntimeException(message); + } + } + + @VisibleForTesting static void initializeResourcesMap(Configuration conf) { Map resourceInformationMap = new HashMap<>(); @@ -246,6 +262,11 @@ static void initializeResourcesMap(Configuration conf) { } } + // Validate names of resource information map. + for (String name : resourceInformationMap.keySet()) { + validateNameOfResourceNameAndThorwException(name); + } + checkMandatoryResources(resourceInformationMap); addMandatoryResources(resourceInformationMap); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceUtils.java index 7a68fb1447d..8fdb95f7f7e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/resource/TestResourceUtils.java @@ -24,6 +24,7 @@ import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.ResourceInformation; import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -311,6 +312,42 @@ public void testGetResourceInformation() throws Exception { } } + @Test + public void testResourceNameFormatValidation() throws Exception { + String[] validNames = new String[] { + "yarn.io/gpu", + "gpu", + "g_1_2", + "123.io/gpu", + "prefix/resource_1", + "a___-3", + "a....b", + }; + + String[] invalidNames = new String[] { + "asd/resource/-name", + "prefix/-resource_1", + "prefix/0123resource", + "0123resource", + "-resource_1", + "........abc" + }; + + for (String validName : validNames) { + ResourceUtils.validateNameOfResourceNameAndThorwException(validName); + } + + for (String invalidName : invalidNames) { + try { + ResourceUtils.validateNameOfResourceNameAndThorwException(invalidName); + Assert.fail("Expected to fail name check, the name=" + invalidName + + " is illegal."); + } catch (YarnRuntimeException e) { + // expected + } + } + } + public static String setupResourceTypes(Configuration conf, String filename) throws Exception { File source = new File(