diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/Times.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/Times.java index f113bd31c4a..3c415586274 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/Times.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/Times.java @@ -105,6 +105,9 @@ public static String formatISO8601(long ts) { */ public static long parseISO8601ToLocalTimeInMillis(String isoString) throws ParseException { + if (isoString == null) { + throw new ParseException("Invalid input.", -1); + } return isoFormat.get().parse(isoString).getTime(); } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMServerUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMServerUtils.java index a0cdf6889e3..74898caecbd 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMServerUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMServerUtils.java @@ -507,7 +507,8 @@ public static Map validateISO8601AndConvertToLocal } catch (ParseException ex) { String message = "Expire time is not in ISO8601 format. ISO8601 supported " - + "format is yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + + "format is yyyy-MM-dd'T'HH:mm:ss.SSSZ. Configured " + + "timeout value is " + timeout.getValue(); throw new YarnException(message, ex); } if (expireTime < currentTimeMillis) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java index a46fb813f0b..bd0602b5eac 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java @@ -2434,7 +2434,7 @@ public ReservationListResponse run() throws IOException, } @GET - @Path("/apps/{appid}/timeout/{type}") + @Path("/apps/{appid}/timeouts/{type}") @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8, MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 }) public AppTimeoutInfo getAppTimeout(@Context HttpServletRequest hsr, @@ -2571,10 +2571,10 @@ public Response updateApplicationTimeout(AppTimeoutInfo appTimeout, private Response updateApplicationTimeouts(final RMApp app, UserGroupInformation callerUGI, final AppTimeoutInfo appTimeout) throws IOException, InterruptedException { - - if (appTimeout.getTimeoutType() == null) { - return Response.status(Status.BAD_REQUEST).entity("Timeout type is null.") - .build(); + if (appTimeout.getTimeoutType() == null + || appTimeout.getExpireTime() == null) { + return Response.status(Status.BAD_REQUEST) + .entity("Timeout type or ExpiryTime is null.").build(); } String userName = callerUGI.getUserName(); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppsModification.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppsModification.java index 64584715d22..5d99e0d169d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppsModification.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppsModification.java @@ -1328,19 +1328,11 @@ public void testUpdateAppTimeout() throws Exception { ApplicationTimeoutType.LIFETIME, "UNLIMITED", -1); } - AppTimeoutInfo timeoutUpdate = new AppTimeoutInfo(); long timeOutFromNow = 60; String expireTime = Times .formatISO8601(System.currentTimeMillis() + timeOutFromNow * 1000); - timeoutUpdate.setTimeoutType(ApplicationTimeoutType.LIFETIME); - timeoutUpdate.setExpiryTime(expireTime); - - Object entity; - if (contentType.equals(MediaType.APPLICATION_JSON_TYPE)) { - entity = appTimeoutToJSON(timeoutUpdate); - } else { - entity = timeoutUpdate; - } + Object entity = getAppTimeoutInfoEntity(ApplicationTimeoutType.LIFETIME, + contentType, expireTime); response = this .constructWebResource("apps", app.getApplicationId().toString(), "timeout") @@ -1361,10 +1353,20 @@ public void testUpdateAppTimeout() throws Exception { expireTime, timeOutFromNow); } + // verify for negative cases + entity = getAppTimeoutInfoEntity(null, + contentType, null); + response = this + .constructWebResource("apps", app.getApplicationId().toString(), + "timeout") + .entity(entity, contentType).accept(mediaType) + .put(ClientResponse.class); + assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo()); + // invoke get response = this.constructWebResource("apps", app.getApplicationId().toString(), - "timeout", ApplicationTimeoutType.LIFETIME.toString()) + "timeouts", ApplicationTimeoutType.LIFETIME.toString()) .accept(mediaType).get(ClientResponse.class); assertResponseStatusCode(Status.OK, response.getStatusInfo()); if (mediaType.contains(MediaType.APPLICATION_JSON)) { @@ -1376,6 +1378,21 @@ public void testUpdateAppTimeout() throws Exception { rm.stop(); } + private Object getAppTimeoutInfoEntity(ApplicationTimeoutType type, + MediaType contentType, String expireTime) throws Exception { + AppTimeoutInfo timeoutUpdate = new AppTimeoutInfo(); + timeoutUpdate.setTimeoutType(type); + timeoutUpdate.setExpiryTime(expireTime); + + Object entity; + if (contentType.equals(MediaType.APPLICATION_JSON_TYPE)) { + entity = appTimeoutToJSON(timeoutUpdate); + } else { + entity = timeoutUpdate; + } + return entity; + } + protected static void verifyAppTimeoutJson(ClientResponse response, ApplicationTimeoutType type, String expireTime, long timeOutFromNow) throws JSONException {