diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/pom.xml b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/pom.xml index 58646bc373c..1ca403a9700 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/pom.xml +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/pom.xml @@ -487,5 +487,4 @@ - diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/AppCatalogSolrClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/AppCatalogSolrClient.java index f3532ae89dd..b1515a5b6fb 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/AppCatalogSolrClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/AppCatalogSolrClient.java @@ -291,13 +291,12 @@ public class AppCatalogSolrClient { docs.add(request); } - // Commit Solr changes. - UpdateResponse detailsResponse = solr.add(docs); - if (detailsResponse.getStatus() != 0) { + try { + commitSolrChanges(solr, docs); + } catch (IOException e) { throw new IOException("Unable to register docker instance " - + "with application entry."); + + "with application entry.", e); } - solr.commit(); } private SolrInputDocument incrementDownload(SolrDocument doc, @@ -350,16 +349,10 @@ public class AppCatalogSolrClient { buffer.setField("yarnfile_s", mapper.writeValueAsString(yarnApp)); docs.add(buffer); - // Commit Solr changes. - UpdateResponse detailsResponse = solr.add(docs); - if (detailsResponse.getStatus() != 0) { - throw new IOException("Unable to register application " + - "in Application Store."); - } - solr.commit(); + commitSolrChanges(solr, docs); } catch (SolrServerException | IOException e) { throw new IOException("Unable to register application " + - "in Application Store. "+ e.getMessage()); + "in Application Store. ", e); } } @@ -389,16 +382,64 @@ public class AppCatalogSolrClient { buffer.setField("yarnfile_s", mapper.writeValueAsString(yarnApp)); docs.add(buffer); - // Commit Solr changes. - UpdateResponse detailsResponse = solr.add(docs); - if (detailsResponse.getStatus() != 0) { - throw new IOException("Unable to register application " + - "in Application Store."); - } - solr.commit(); + commitSolrChanges(solr, docs); } catch (SolrServerException | IOException e) { throw new IOException("Unable to register application " + - "in Application Store. "+ e.getMessage()); + "in Application Store. ", e); } } + + public void upgradeApp(Service service) throws IOException, + SolrServerException { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + Collection docs = new HashSet(); + SolrClient solr = getSolrClient(); + if (service!=null) { + String name = service.getName(); + String app = ""; + SolrQuery query = new SolrQuery(); + query.setQuery("id:" + name); + query.setFilterQueries("type_s:AppEntry"); + query.setRows(1); + + QueryResponse response; + try { + response = solr.query(query); + Iterator appList = response.getResults().listIterator(); + while (appList.hasNext()) { + SolrDocument d = appList.next(); + app = d.get("app_s").toString(); + } + } catch (SolrServerException | IOException e) { + LOG.error("Error in finding deployed application: " + name, e); + } + // Register deployed application instance with AppList + SolrInputDocument request = new SolrInputDocument(); + request.addField("type_s", "AppEntry"); + request.addField("id", name); + request.addField("name_s", name); + request.addField("app_s", app); + request.addField("yarnfile_s", mapper.writeValueAsString(service)); + docs.add(request); + } + try { + commitSolrChanges(solr, docs); + } catch (IOException e) { + throw new IOException("Unable to register docker instance " + + "with application entry.", e); + } + } + + private void commitSolrChanges(SolrClient solr, + Collection docs) + throws IOException, SolrServerException { + // Commit Solr changes. + UpdateResponse detailsResponse = solr.add(docs); + if (detailsResponse.getStatus() != 0) { + throw new IOException("Failed to commit document in solr, status code: " + + detailsResponse.getStatus()); + } + solr.commit(); + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/YarnServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/YarnServiceClient.java index 667d2187ec3..3a6c67d7370 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/YarnServiceClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/application/YarnServiceClient.java @@ -27,6 +27,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.yarn.appcatalog.model.AppEntry; import org.apache.hadoop.yarn.service.api.records.Service; +import org.apache.hadoop.yarn.service.api.records.ServiceState; import org.apache.hadoop.yarn.service.api.records.KerberosPrincipal; import org.apache.hadoop.yarn.service.client.ApiServiceClient; @@ -171,4 +172,25 @@ public class YarnServiceClient { LOG.error("Error in fetching application status: ", e); } } + + public void upgradeApp(Service app) throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + String appInstanceId = app.getName(); + app.setState(ServiceState.EXPRESS_UPGRADING); + String yarnFile = mapper.writeValueAsString(app); + ClientResponse response; + try { + response = asc.getApiClient(asc.getServicePath(appInstanceId)) + .put(ClientResponse.class, yarnFile); + if (response.getStatus() >= 299) { + String message = response.getEntity(String.class); + throw new RuntimeException("Failed : HTTP error code : " + + response.getStatus() + " error: " + message); + } + } catch (UniformInterfaceException | ClientHandlerException + | IOException e) { + LOG.error("Error in stopping application: ", e); + } + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java index db6973d20c4..63aefa615ff 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java @@ -18,8 +18,12 @@ package org.apache.hadoop.yarn.appcatalog.controller; +import java.io.IOException; + +import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -32,6 +36,7 @@ import org.apache.hadoop.yarn.appcatalog.application.YarnServiceClient; import org.apache.hadoop.yarn.appcatalog.model.AppEntry; import org.apache.hadoop.yarn.service.api.records.Service; import org.apache.hadoop.yarn.service.api.records.ServiceState; +import org.apache.solr.client.solrj.SolrServerException; import com.fasterxml.jackson.core.JsonProcessingException; @@ -262,4 +267,33 @@ public class AppDetailsController { } return Response.ok().build(); } + + /** + * Upgrade an application. + * + * @apiGroup AppDetailController + * @apiName upgradeApp + * @api {put} /app_details/upgrade/{id} Upgrade one instance of application. + * @apiParam {String} id Application Name to upgrade. + * @apiSuccess {String} text + * @apiError BadRequest Requested application does not upgrade. + * @return Web response code + */ + @Path("upgrade/{id}") + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response upgradeApp(@PathParam("id") String id, Service app) { + try { + AppCatalogSolrClient sc = new AppCatalogSolrClient(); + sc.upgradeApp(app); + YarnServiceClient yc = new YarnServiceClient(); + yc.upgradeApp(app); + } catch (IOException | SolrServerException e) { + return Response.status(Status.BAD_REQUEST).entity(e.toString()).build(); + } + String output = "{\"status\":\"Application upgrade requested.\",\"id\":\"" + + app.getName() + "\"}"; + return Response.status(Status.ACCEPTED).entity(output).build(); + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/app.js index 0a7b6dbfff3..4cab2b4ddcc 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/app.js @@ -53,6 +53,9 @@ app.config(['$routeProvider', }).when('/deploy/:id', { templateUrl: 'partials/deploy.html', controller: 'DeployAppController' + }).when('/upgrade/:id', { + templateUrl: 'partials/upgrade.html', + controller: 'UpgradeAppController' }).otherwise({ redirectTo: '/' }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/controllers.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/controllers.js index 241f15db7ec..4d9e42d3277 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/controllers.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/javascript/controllers.js @@ -127,6 +127,10 @@ controllers.controller("AppDetailsController", [ '$scope', '$interval', '$rootSc }, errorCallback); } + $scope.upgradeApp = function(id) { + window.location = '/#!/upgrade/' + id; + } + $scope.canDeployApp = function() { return true; }; @@ -306,6 +310,56 @@ controllers.controller("DeployAppController", [ '$scope', '$rootScope', '$http', }]); +controllers.controller("UpgradeAppController", [ '$scope', '$rootScope', '$http', + '$routeParams', function($scope, $rootScope, $http, $routeParams) { + $scope.message = null; + $scope.error = null; + $scope.appName = $routeParams.id; + $scope.refreshAppDetails = function() { + $http({ + method : 'GET', + url : '/v1/app_details/status/' + $scope.appName + }).then(successCallback, errorCallback); + } + + $scope.upgradeApp = function(app) { + $rootScope.$emit("showLoadScreen", {}); + $http({ + method : 'PUT', + url : '/v1/app_details/upgrade/' + $scope.appName, + data : JSON.stringify($scope.details) + }).then(function(data, status, headers, config) { + $rootScope.$emit("RefreshAppList", {}); + window.location = '/#!/app/' + data.data.id; + }, function(data, status, headers, config) { + $rootScope.$emit("hideLoadScreen", {}); + $scope.error = data.data; + $('#error-message').html(data.data); + $('#myModal').modal('show'); + console.log('error', data, status); + }); + } + + function successCallback(response) { + if (response.data.yarnfile.components.length!=0) { + $scope.details = response.data.yarnfile; + } else { + // When application is in accepted or failed state, it does not + // have components detail, hence we update states only. + $scope.details.state = response.data.yarnfile.state; + } + } + + function errorCallback(response) { + $rootScope.$emit("hideLoadScreen", {}); + $scope.error = "Error in getting application detail."; + $('#error-message').html($scope.error); + $('#myModal').modal('show'); + } + + $scope.refreshAppDetails(); +}]); + controllers.controller("LoadScreenController", [ '$scope', '$rootScope', '$http', function($scope, $rootScope, $http) { $scope.loadScreen = "hide"; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/css/bootstrap-hadoop.css b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/css/bootstrap-hadoop.css index 5aa6e46656b..231f9a998f2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/css/bootstrap-hadoop.css +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/css/bootstrap-hadoop.css @@ -184,6 +184,11 @@ background-color: #FFF; box-shadow: 0 0 2px 0 #1391c1; } +.btn-secondary:visited { + color: #429929; + background-color: #FFF; + box-shadow: 0 0 2px 0 #1391c1; +} .btn-secondary[disabled], .btn-secondary:focus[disabled], .btn-secondary.disabled, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/partials/details.html b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/partials/details.html index 69ef9126346..8624440ea43 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/partials/details.html +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/partials/details.html @@ -14,8 +14,9 @@
+ Start Stop - Start + Upgrade diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/partials/upgrade.html b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/partials/upgrade.html new file mode 100644 index 00000000000..2453aabdecb --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/partials/upgrade.html @@ -0,0 +1,114 @@ + +
+
+
+
+

Upgrade Application

+
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+

+ Upgrade + CANCEL +

+
+ + +
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/theme.html b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/theme.html index a8a2a2d6a71..57982d1a9b5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/theme.html +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/webapp/theme.html @@ -29,7 +29,7 @@ - + diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/application/TestAppCatalogSolrClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/application/TestAppCatalogSolrClient.java index 16bf7fbb7c6..d902de5c8cd 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/application/TestAppCatalogSolrClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/application/TestAppCatalogSolrClient.java @@ -18,6 +18,7 @@ package org.apache.hadoop.yarn.appcatalog.application; +import org.apache.hadoop.yarn.appcatalog.model.AppEntry; import org.apache.hadoop.yarn.appcatalog.model.AppStoreEntry; import org.apache.hadoop.yarn.appcatalog.model.Application; import org.apache.solr.client.solrj.SolrClient; @@ -127,4 +128,22 @@ public class TestAppCatalogSolrClient { } } + @Test + public void testUpgradeApp() throws Exception { + Application example = new Application(); + String expected = "2.0"; + String actual = ""; + example.setOrganization("jenkins-ci.org"); + example.setVersion("1.0"); + example.setName("jenkins"); + example.setDescription("World leading open source automation system."); + example.setIcon("/css/img/feather.png"); + spy.register(example); + spy.deployApp("test", example); + example.setVersion("2.0"); + spy.upgradeApp(example); + List appEntries = spy.listAppEntries(); + actual = appEntries.get(appEntries.size() -1).getYarnfile().getVersion(); + assertEquals(expected, actual); + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsControllerTest.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsControllerTest.java index ca4fba9bbd2..437d50b737b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsControllerTest.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsControllerTest.java @@ -135,4 +135,23 @@ public class AppDetailsControllerTest { is("/app_details")); } + @Test + public void testUpgradeApp() throws Exception { + String id = "application1"; + AppDetailsController ac = Mockito.mock(AppDetailsController.class); + + Service yarnfile = new Service(); + yarnfile.setVersion("1.0"); + Component comp = new Component(); + Container c = new Container(); + c.setId("container-1"); + List containers = new ArrayList(); + containers.add(c); + comp.setContainers(containers); + yarnfile.addComponent(comp); + Response expected = Response.ok().build(); + when(ac.upgradeApp(id, yarnfile)).thenReturn(Response.ok().build()); + final Response actual = ac.upgradeApp(id, yarnfile); + assertEquals(expected.getStatus(), actual.getStatus()); + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/resources/configsets/exampleCollection/conf/schema.xml b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/resources/configsets/exampleCollection/conf/schema.xml index 20acbc92b46..0921e132da2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/resources/configsets/exampleCollection/conf/schema.xml +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/test/resources/configsets/exampleCollection/conf/schema.xml @@ -23,6 +23,7 @@ +