KYLIN-1128 clone cube metadata
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/25ac10a6 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/25ac10a6 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/25ac10a6 Branch: refs/heads/master Commit: 25ac10a626244786a539c9c49ab85aa48f6bdab0 Parents: b0c5fd3 Author: Zhong <jiazh...@lm-shc-16501192.corp.ebay.com> Authored: Tue Nov 24 19:15:41 2015 +0800 Committer: jian <jiazh...@apache.org> Committed: Tue Dec 8 11:03:05 2015 +0800 ---------------------------------------------------------------------- .../kylin/rest/controller/CubeController.java | 44 ++++++++++++ webapp/app/js/controllers/cubes.js | 67 +++++++++++++++++ webapp/app/js/services/cubes.js | 1 + webapp/app/less/app.less | 6 +- webapp/app/partials/cubes/cube_clone.html | 76 ++++++++++++++++++++ webapp/app/partials/cubes/cubes.html | 2 + 6 files changed, 195 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/25ac10a6/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java index b94ded3..a8c28c4 100644 --- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java +++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java @@ -256,6 +256,50 @@ public class CubeController extends BasicController { } } + @RequestMapping(value = "/{cubeName}/clone", method = { RequestMethod.PUT }) + @ResponseBody + public CubeInstance cloneCube(@PathVariable String cubeName,@RequestBody CubeRequest cubeRequest) { + String targetCubeName = cubeRequest.getCubeName(); + String targetModelName = cubeRequest.getModelDescData(); + String project = cubeRequest.getProject(); + + CubeInstance cube = cubeService.getCubeManager().getCube(cubeName); + if (cube == null) { + throw new InternalErrorException("Cannot find cube " + cubeName); + } + + CubeDesc cubeDesc = cube.getDescriptor(); + + String modelName = cubeDesc.getModelName(); + MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv()); + + DataModelDesc modelDesc = metaManager.getDataModelDesc(modelName); + + modelDesc.setName(targetModelName); + modelDesc.setLastModified(0); + modelDesc.setUuid(UUID.randomUUID().toString()); + try { + metaManager.createDataModelDesc(modelDesc); + } catch (IOException e) { + throw new InternalErrorException("failed to clone DataModelDesc",e); + } + + cubeDesc.setName(targetCubeName); + cubeDesc.setLastModified(0); + cubeDesc.setUuid(UUID.randomUUID().toString()); + cubeDesc.setModelName(targetModelName); + CubeInstance newCube = null; + try { + newCube = cubeService.createCubeAndDesc(targetCubeName,project,cubeDesc); + } catch (IOException e) { + throw new InternalErrorException("failed to clone DataModelDesc",e); + } + + return newCube; + + } + + @RequestMapping(value = "/{cubeName}/enable", method = { RequestMethod.PUT }) @ResponseBody public CubeInstance enableCube(@PathVariable String cubeName) { http://git-wip-us.apache.org/repos/asf/kylin/blob/25ac10a6/webapp/app/js/controllers/cubes.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js index 75bcb6d..9f538b0 100755 --- a/webapp/app/js/controllers/cubes.js +++ b/webapp/app/js/controllers/cubes.js @@ -354,6 +354,21 @@ KylinApp }; + $scope.cloneCube = function(cube){ + $scope.loadDetail(cube).then(function () { + $modal.open({ + templateUrl: 'cubeClone.html', + controller: cubeCloneCtrl, + windowClass:"clone-cube-window", + resolve: { + cube: function () { + return cube; + } + } + }); + }); + } + $scope.cubeEdit = function (cube) { $location.path("cubes/edit/" + cube.name); } @@ -376,6 +391,58 @@ KylinApp } }); +var cubeCloneCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube, MetaModel, SweetAlert,ProjectModel, loadingRequest) { + $scope.projectModel = ProjectModel; + + $scope.targetObj={ + cubeName:cube.descriptor+"_clone", + modelName:cube.model.name+"_clone" + } + + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; + + $scope.cloneCube = function(){ + + $scope.cubeRequest = { + cubeName:$scope.targetObj.cubeName, + modelDescData:$scope.targetObj.modelName, + project:$scope.projectModel.selectedProject + } + + SweetAlert.swal({ + title: '', + text: 'Are you sure to clone the cube? ', + type: '', + showCancelButton: true, + confirmButtonColor: '#DD6B55', + confirmButtonText: "Yes", + closeOnConfirm: true + }, function (isConfirm) { + if (isConfirm) { + + loadingRequest.show(); + CubeService.clone({cubeId: cube.name}, $scope.cubeRequest, function (result) { + loadingRequest.hide(); + SweetAlert.swal('Success!', 'Clone cube successfully', 'success'); + location.reload(); + }, function (e) { + loadingRequest.hide(); + if (e.data && e.data.exception) { + var message = e.data.exception; + var msg = !!(message) ? message : 'Failed to take action.'; + SweetAlert.swal('Oops...', msg, 'error'); + } else { + SweetAlert.swal('Oops...', "Failed to take action.", 'error'); + } + }); + } + }); + } + +} + var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube, MetaModel, buildType, SweetAlert, loadingRequest) { $scope.cube = cube; $scope.metaModel = { http://git-wip-us.apache.org/repos/asf/kylin/blob/25ac10a6/webapp/app/js/services/cubes.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/services/cubes.js b/webapp/app/js/services/cubes.js index 3dfd2c5..a18736f 100644 --- a/webapp/app/js/services/cubes.js +++ b/webapp/app/js/services/cubes.js @@ -28,6 +28,7 @@ KylinApp.factory('CubeService', ['$resource', function ($resource, config) { disable: {method: 'PUT', params: {action: 'disable'}, isArray: false}, enable: {method: 'PUT', params: {action: 'enable'}, isArray: false}, purge: {method: 'PUT', params: {action: 'purge'}, isArray: false}, + clone: {method: 'PUT', params: {action: 'clone'}, isArray: false}, drop: {method: 'DELETE', params: {}, isArray: false}, save: {method: 'POST', params: {}, isArray: false}, update: {method: 'PUT', params: {}, isArray: false}, http://git-wip-us.apache.org/repos/asf/kylin/blob/25ac10a6/webapp/app/less/app.less ---------------------------------------------------------------------- diff --git a/webapp/app/less/app.less b/webapp/app/less/app.less index 4edf83c..6243f6f 100644 --- a/webapp/app/less/app.less +++ b/webapp/app/less/app.less @@ -312,6 +312,10 @@ body .modal-dialog { margin-right:auto; } +.clone-cube-window .modal-dialog { + width: 600px; /* desired relative width */ +} + pre { width: inherit; height: 350px; @@ -621,4 +625,4 @@ ul.messenger .messenger-message-inner ,.ngCellText{ .text-muted { color: #777; } -.tick line {display: none;} \ No newline at end of file +.tick line {display: none;} http://git-wip-us.apache.org/repos/asf/kylin/blob/25ac10a6/webapp/app/partials/cubes/cube_clone.html ---------------------------------------------------------------------- diff --git a/webapp/app/partials/cubes/cube_clone.html b/webapp/app/partials/cubes/cube_clone.html new file mode 100644 index 0000000..a20555b --- /dev/null +++ b/webapp/app/partials/cubes/cube_clone.html @@ -0,0 +1,76 @@ +<!-- +* 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. +--> + +<script type="text/ng-template" id="cubeClone.html"> + <div class="modal-header"> + <h4 tooltip="submit">CUBE CLONE</h4> + </div> + <div class="modal-body" style="background-color: white"> + + <div class="row"> + <div class="col-md-2"></div> + <div class="col-md-8"> + <div class="row"> + <div class="form-group"> + <b>Target Project is:</b> + <br/> + <select ng-required="projectModel.projects.length" chosen ng-model="projectModel.selectedProject" + ng-init="newAccess.permission=permissions.READ.value;" + ng-options="project as project for project in projectModel.projects " + style="width: 100% !important;" + data-placeholder="select a project" + class="chosen-select"> + <option value=""></option> + </select> + </div> + </div> + </div> + <div class="col-md-2"></div> + </div> + <div class="row"> + <div class="col-md-2"></div> + <div class="col-md-8"> + <div class="row"> + <div class="form-group"> + <b>New Cube Name:</b> + <br/> + <input type="text" class="form-control" ng-model="targetObj.cubeName"/> + </div> + </div> + </div> + <div class="col-md-2"></div> + </div> + <div class="row"> + <div class="col-md-2"></div> + <div class="col-md-8"> + <div class="row"> + <div class="form-group"> + <b>New Model Name:</b> + <br/> + <input type="text" class="form-control" ng-model="targetObj.modelName"/> + </div> + </div> + </div> + <div class="col-md-2"></div> + </div> + </div> + <div class="modal-footer"> + <button class="btn btn-success" ng-click="cloneCube()">Submit</button> + <button class="btn btn-primary" ng-click="cancel()">Close</button> + </div> +</script> http://git-wip-us.apache.org/repos/asf/kylin/blob/25ac10a6/webapp/app/partials/cubes/cubes.html ---------------------------------------------------------------------- diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html index 618dbce..74fba5c 100644 --- a/webapp/app/partials/cubes/cubes.html +++ b/webapp/app/partials/cubes/cubes.html @@ -121,6 +121,7 @@ <li ng-if="cube.status!='DISABLED'"><a ng-click="disable(cube)">Disable</a></li> <li ng-if="cube.status=='DISABLED'"><a ng-click="enable(cube)">Enable</a></li> <li ng-if="cube.status=='DISABLED'"><a ng-click="purge(cube)">Purge</a></li> + <li><a ng-click="cloneCube(cube)">Clone</a></li> </ul> </div> @@ -157,6 +158,7 @@ <strong>Storage: {{getTotalSize(cubeList.cubes)}}</strong> </div> +<div ng-include="'partials/cubes/cube_clone.html'"></div> <div ng-include="'partials/jobs/job_submit.html'"></div> <div ng-include="'partials/jobs/job_refresh.html'"></div> <div ng-include="'partials/jobs/job_merge.html'"></div>