AMBARI-19674. Asset Manager import and validation issues (Madhan Mohan Reddy via pallavkul)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/74aff7c6 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/74aff7c6 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/74aff7c6 Branch: refs/heads/branch-dev-patch-upgrade Commit: 74aff7c645c987b692188e0a48e627896e6cf70a Parents: a6fd5cb Author: pallavkul <pallav....@gmail.com> Authored: Mon Jan 23 18:23:57 2017 +0530 Committer: pallavkul <pallav....@gmail.com> Committed: Mon Jan 23 18:23:57 2017 +0530 ---------------------------------------------------------------------- .../org/apache/oozie/ambari/view/Constants.java | 16 +++-- .../apache/oozie/ambari/view/HDFSFileUtils.java | 19 ++++++ .../ambari/view/OozieProxyImpersonator.java | 40 ++++++++++- .../oozie/ambari/view/WorkflowFilesService.java | 70 ++++++++++++-------- .../oozie/ambari/view/assets/AssetRepo.java | 10 +++ .../oozie/ambari/view/assets/AssetResource.java | 7 ++ .../oozie/ambari/view/assets/AssetService.java | 4 ++ .../workflowmanager/WorkflowManagerService.java | 46 ++++++------- .../view/workflowmanager/WorkflowsRepo.java | 19 +++++- .../resources/ui/app/components/asset-config.js | 18 ++++- .../resources/ui/app/components/asset-list.js | 20 +++++- .../ui/app/components/asset-manager.js | 51 ++++++++++++-- .../ui/app/components/designer-workspace.js | 23 +------ .../ui/app/components/flow-designer.js | 59 ++++++++--------- .../resources/ui/app/services/asset-manager.js | 19 ++++++ .../src/main/resources/ui/app/styles/app.less | 4 ++ .../app/templates/components/asset-config.hbs | 8 +++ .../ui/app/templates/components/asset-list.hbs | 12 +++- .../app/templates/components/asset-manager.hbs | 26 +++++++- .../templates/components/designer-workspace.hbs | 2 +- .../app/templates/components/flow-designer.hbs | 4 +- 21 files changed, 347 insertions(+), 130 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Constants.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Constants.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Constants.java index 238b002..f7c1936 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Constants.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Constants.java @@ -17,9 +17,15 @@ */ package org.apache.oozie.ambari.view; -public class Constants { - public static final String STATUS_FAILED = "failed"; - public static final String STATUS_OK = "ok"; - public static final String STATUS_KEY = "status"; - public static final String MESSAGE_KEY = "message"; +public interface Constants { + String STATUS_FAILED = "failed"; + String STATUS_OK = "ok"; + String STATUS_KEY = "status"; + String MESSAGE_KEY = "message"; + String WF_DRAFT_EXTENSION = ".wfdraft"; + String WF_EXTENSION = ".xml"; + String DEFAULT_WORKFLOW_FILENAME="workflow.xml"; + String DEFAULT_DRAFT_FILENAME="workflow"+WF_DRAFT_EXTENSION; + String WF_ASSET_EXTENSION = ".wfasset"; + String DEFAULT_WORKFLOW_ASSET_FILENAME="asset"+WF_ASSET_EXTENSION; } http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java index 53b43f9..d06eb07 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java @@ -19,6 +19,7 @@ package org.apache.oozie.ambari.view; import com.google.common.base.Optional; import org.apache.ambari.view.ViewContext; +import org.apache.ambari.view.commons.hdfs.UserService; import org.apache.ambari.view.commons.hdfs.ViewPropertyHelper; import org.apache.ambari.view.utils.hdfs.HdfsApi; import org.apache.ambari.view.utils.hdfs.HdfsUtil; @@ -30,6 +31,7 @@ import org.slf4j.LoggerFactory; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.HashMap; import java.util.Map; public class HDFSFileUtils { @@ -118,5 +120,22 @@ public class HDFSFileUtils { } } + public boolean hdfsCheck() { + try { + getHdfsgetApi().getStatus(); + return true; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + public boolean homeDirCheck(){ + UserService userservice = new UserService(viewContext, getViewConfigs(viewContext)); + userservice.homeDir(); + return true; + } + private Map<String,String> getViewConfigs(ViewContext context) { + Optional<Map<String, String>> props = ViewPropertyHelper.getViewConfigs(context, VIEW_CONF_KEYVALUES); + return props.isPresent()? props.get() : new HashMap<String, String>(); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java index 7596de0..d029c39 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java @@ -122,6 +122,16 @@ public class OozieProxyImpersonator { viewContext.getInstanceName())); } + @Path("hdfsCheck") + public Response hdfsCheck(){ + hdfsFileUtils.hdfsCheck(); + return Response.ok().build(); + } + @Path("homeDirCheck") + public Response homeDirCheck(){ + hdfsFileUtils.homeDirCheck(); + return Response.ok().build(); + } @Path("/fileServices") public FileServices fileServices() { @@ -210,7 +220,7 @@ public class OozieProxyImpersonator { if (StringUtils.isEmpty(appPath)) { throw new RuntimeException("app path can't be empty."); } - appPath = workflowFilesService.getWorkflowDrafFileName(appPath.trim()); + appPath = workflowFilesService.getWorkflowDraftFileName(appPath.trim()); workflowFilesService.createFile(appPath, postBody, overwrite); if (PROJ_MANAGER_ENABLED) { JobType jobType = StringUtils.isEmpty(jobTypeStr) ? JobType.WORKFLOW : JobType.valueOf(jobTypeStr); @@ -263,6 +273,30 @@ public class OozieProxyImpersonator { return getRespCodeForException(ex); } } + @GET + @Path("/readAsset") + public Response readAsset( + @QueryParam("assetPath") String assetPath) { + if (StringUtils.isEmpty(assetPath)) { + throw new RuntimeException("assetPath can't be empty."); + } + try { + final InputStream is = workflowFilesService + .readAssset(assetPath); + StreamingOutput streamer = new StreamingOutput() { + @Override + public void write(OutputStream os) throws IOException, + WebApplicationException { + IOUtils.copy(is, os); + is.close(); + os.close(); + } + }; + return Response.ok(streamer).status(200).build(); + } catch (IOException e) { + return getRespCodeForException(e); + } + } @GET @@ -375,7 +409,7 @@ public class OozieProxyImpersonator { @GET @Path("/readWorkflowDetail") - public Response isDraftAvailable( + public Response getWorkflowDetail( @QueryParam("workflowXmlPath") String workflowPath) { WorkflowFileInfo workflowDetails = workflowFilesService .getWorkflowDetails(workflowPath); @@ -384,7 +418,7 @@ public class OozieProxyImpersonator { @GET @Path("/readWorkflowXml") - public Response readWorkflowXxml( + public Response readWorkflowXml( @QueryParam("workflowXmlPath") String workflowPath) { if (StringUtils.isEmpty(workflowPath)) { throw new RuntimeException("workflowXmlPath can't be empty."); http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/WorkflowFilesService.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/WorkflowFilesService.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/WorkflowFilesService.java index d8bf9ff..289e68b 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/WorkflowFilesService.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/WorkflowFilesService.java @@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory; public class WorkflowFilesService { private final static Logger LOGGER = LoggerFactory - .getLogger(WorkflowFilesService.class); + .getLogger(WorkflowFilesService.class); private HDFSFileUtils hdfsFileUtils; public WorkflowFilesService(HDFSFileUtils hdfsFileUtils) { @@ -35,86 +35,104 @@ public class WorkflowFilesService { } public String createFile(String appPath, String content, - boolean overwrite) throws IOException { + boolean overwrite) throws IOException { return hdfsFileUtils.writeToFile(appPath, content, - overwrite); + overwrite); } public String createAssetFile(String appPath, String content, boolean overwrite) throws IOException { return hdfsFileUtils.writeToFile(appPath, content, - overwrite); + overwrite); } public InputStream readDraft(String appPath) throws IOException { - return hdfsFileUtils.read(getWorkflowDrafFileName(appPath)); + return hdfsFileUtils.read(getWorkflowDraftFileName(appPath)); } public InputStream readWorkflowXml(String appPath) throws IOException { return hdfsFileUtils.read(getWorkflowFileName(appPath)); } - public String getWorkflowDrafFileName(String appPath) { - if (appPath.endsWith(".draft.json")){ + public InputStream readAssset(String assetPath) throws IOException { + return hdfsFileUtils.read(getAssetFileName(assetPath)); + } + + public String getWorkflowDraftFileName(String appPath) { + if (appPath.endsWith(Constants.WF_DRAFT_EXTENSION)) { return appPath; - }else{ - return getWorkflowFileName(appPath).concat(".draft.json"); + } else if (appPath.endsWith(Constants.WF_EXTENSION)) { + String folderPath = appPath.substring(0, appPath.lastIndexOf(Constants.WF_EXTENSION)); + return folderPath + Constants.WF_DRAFT_EXTENSION; + } else if (appPath.endsWith("/")) { + return appPath + Constants.DEFAULT_DRAFT_FILENAME; + } else { + return appPath + "/" + Constants.DEFAULT_DRAFT_FILENAME; } } public String getWorkflowFileName(String appPath) { - String workflowFile = null; - if (appPath.endsWith(".xml")) { - workflowFile = appPath; + if (appPath.endsWith(Constants.WF_EXTENSION)) { + return appPath; + } else if (appPath.endsWith(Constants.WF_DRAFT_EXTENSION)) { + String folderPath = appPath.substring(0, appPath.lastIndexOf(Constants.WF_DRAFT_EXTENSION)); + return folderPath + Constants.WF_EXTENSION; + } else if (appPath.endsWith("/")) { + return appPath + Constants.DEFAULT_WORKFLOW_FILENAME; } else { - workflowFile = appPath + (appPath.endsWith("/") ? "" : "/") - + "workflow.xml"; + return appPath + "/" + Constants.DEFAULT_WORKFLOW_FILENAME; } - return workflowFile; } public String getAssetFileName(String appPath) { String assetFile = null; - if (appPath.endsWith(".xml")) { + if (appPath.endsWith(Constants.WF_ASSET_EXTENSION)) { assetFile = appPath; } else { assetFile = appPath + (appPath.endsWith("/") ? "" : "/") - + "asset.xml"; + + Constants.DEFAULT_WORKFLOW_ASSET_FILENAME; } return assetFile; } public void discardDraft(String workflowPath) throws IOException { - hdfsFileUtils.deleteFile(getWorkflowDrafFileName(workflowPath)); - + hdfsFileUtils.deleteFile(getWorkflowDraftFileName(workflowPath)); } public WorkflowFileInfo getWorkflowDetails(String appPath) { WorkflowFileInfo workflowInfo = new WorkflowFileInfo(); workflowInfo.setWorkflowPath(getWorkflowFileName(appPath)); boolean draftExists = hdfsFileUtils - .fileExists(getWorkflowDrafFileName(appPath)); + .fileExists(getWorkflowDraftFileName(appPath)); workflowInfo.setDraftExists(draftExists); boolean workflowExists = hdfsFileUtils.fileExists(getWorkflowFileName(appPath)); FileStatus workflowFileStatus = null; if (workflowExists) { workflowFileStatus = hdfsFileUtils - .getFileStatus(getWorkflowFileName(appPath)); + .getFileStatus(getWorkflowFileName(appPath)); workflowInfo.setWorkflowModificationTime(workflowFileStatus - .getModificationTime()); + .getModificationTime()); } if (draftExists) { FileStatus draftFileStatus = hdfsFileUtils - .getFileStatus(getWorkflowDrafFileName(appPath)); + .getFileStatus(getWorkflowDraftFileName(appPath)); workflowInfo.setDraftModificationTime(draftFileStatus - .getModificationTime()); + .getModificationTime()); if (!workflowExists) { workflowInfo.setIsDraftCurrent(true); } else { workflowInfo.setIsDraftCurrent(draftFileStatus.getModificationTime() - - workflowFileStatus.getModificationTime() > 0); + - workflowFileStatus.getModificationTime() > 0); } } return workflowInfo; } -} + public void deleteWorkflowFile(String fullWorkflowFilePath){ + try { + hdfsFileUtils.deleteFile(fullWorkflowFilePath); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetRepo.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetRepo.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetRepo.java index df936a4..6e9b7ee 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetRepo.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetRepo.java @@ -36,4 +36,14 @@ public class AssetRepo extends BaseRepo<ActionAsset> { throw new RuntimeException(e); } } + + public boolean assetNameAvailable(String name) { + try { + Collection<ActionAsset> assets=dataStore.findAll(ActionAsset.class, " name='" + name + "'"); + boolean assetExists= assets!=null && !assets.isEmpty(); + return !assetExists; + } catch (PersistenceException e) { + throw new RuntimeException(e); + } + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetResource.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetResource.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetResource.java index 0622971..af86810 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetResource.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetResource.java @@ -145,6 +145,13 @@ public class AssetResource { } @GET + @Path("/assetNameAvailable") + public Response assetNameAvailable(@QueryParam("name") String name){ + boolean available=assetService.isAssetNameAvailable(name); + return Response.ok(available).build(); + } + + @GET @Path("/{id}") public Response getAssetDetail(@PathParam("id") String id) { try { http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetService.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetService.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetService.java index 9fe2f9c..4bac2cd 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetService.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/assets/AssetService.java @@ -112,4 +112,8 @@ public class AssetService { public Collection<ActionAsset> getMyAssets() { return assetRepo.getMyAsets(viewContext.getUsername()); } + + public boolean isAssetNameAvailable(String name) { + return assetRepo.assetNameAvailable(name); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowManagerService.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowManagerService.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowManagerService.java index afdee9e..7ce6081 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowManagerService.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowManagerService.java @@ -17,26 +17,26 @@ */ package org.apache.oozie.ambari.view.workflowmanager; -import java.io.IOException; -import java.util.Collection; -import java.util.Date; - import org.apache.ambari.view.ViewContext; import org.apache.oozie.ambari.view.HDFSFileUtils; import org.apache.oozie.ambari.view.JobType; +import org.apache.oozie.ambari.view.WorkflowFilesService; import org.apache.oozie.ambari.view.workflowmanager.model.Workflow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collection; + public class WorkflowManagerService { private final static Logger LOGGER = LoggerFactory - .getLogger(WorkflowManagerService.class); + .getLogger(WorkflowManagerService.class); private final WorkflowsRepo workflowsRepository; - private final HDFSFileUtils hdfsFileUtils; + private final WorkflowFilesService workflowFilesService; public WorkflowManagerService(ViewContext viewContext) { workflowsRepository = new WorkflowsRepo(viewContext.getDataStore()); - hdfsFileUtils = new HDFSFileUtils(viewContext); + + workflowFilesService = new WorkflowFilesService(new HDFSFileUtils(viewContext)); } public void saveWorkflow(String projectId, String path, JobType jobType, @@ -46,16 +46,24 @@ public class WorkflowManagerService { Workflow workflowById = workflowsRepository.findById(projectId); if (workflowById == null) { throw new RuntimeException("could not find project with id :" - + projectId); + + projectId); } setWorkflowAttributes(jobType, userName, name, workflowById); workflowsRepository.update(workflowById); + } else { - Workflow wf = new Workflow(); - wf.setId(workflowsRepository.generateId()); - setWorkflowAttributes(jobType, userName, name, wf); - wf.setWorkflowDefinitionPath(path); - workflowsRepository.create(wf); + String workflowFileName = workflowFilesService.getWorkflowFileName(path); + Workflow workflowByPath = workflowsRepository.getWorkflowByPath(workflowFileName); + if (workflowByPath!=null){ + setWorkflowAttributes(jobType, userName, name, workflowByPath); + workflowsRepository.update(workflowByPath); + }else{ + Workflow wf = new Workflow(); + wf.setId(workflowsRepository.generateId()); + setWorkflowAttributes(jobType, userName, name, wf); + wf.setWorkflowDefinitionPath(workflowFileName); + workflowsRepository.create(wf); + } } } @@ -70,19 +78,11 @@ public class WorkflowManagerService { return workflowsRepository.findAll(); } - public Workflow getWorkflowByPath(String path) { - return workflowsRepository.getWorkflowByPath(path); - } - public void deleteWorkflow(String projectId, Boolean deleteDefinition) { Workflow workflow = workflowsRepository.findById(projectId); if (deleteDefinition) { - try { - hdfsFileUtils.deleteFile(workflow.getWorkflowDefinitionPath()); - } catch (IOException e) { - throw new RuntimeException(e); - } + workflowFilesService.deleteWorkflowFile(workflow.getWorkflowDefinitionPath()); } workflowsRepository.delete(workflow); } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowsRepo.java ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowsRepo.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowsRepo.java index 7787bda..1fc0c5f 100644 --- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowsRepo.java +++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/workflowmanager/WorkflowsRepo.java @@ -21,9 +21,14 @@ import org.apache.ambari.view.DataStore; import org.apache.ambari.view.PersistenceException; import org.apache.oozie.ambari.view.repo.BaseRepo; import org.apache.oozie.ambari.view.workflowmanager.model.Workflow; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class WorkflowsRepo extends BaseRepo<Workflow> { +import java.util.Collection; +public class WorkflowsRepo extends BaseRepo<Workflow> { + private final static Logger LOGGER = LoggerFactory + .getLogger(WorkflowsRepo.class); public WorkflowsRepo(DataStore dataStore) { super(Workflow.class, dataStore); @@ -31,8 +36,16 @@ public class WorkflowsRepo extends BaseRepo<Workflow> { public Workflow getWorkflowByPath(String path) { try { - return this.dataStore.find(Workflow.class, - "workflowDefinitionPath='" + path + "'"); + Collection<Workflow> workflows = this.dataStore.findAll(Workflow.class, + "workflowDefinitionPath='" + path + "'"); + if (workflows == null || workflows.isEmpty()) { + return null; + } else if (workflows.size() > 1) { + LOGGER.error("Duplicate workflows found having same path"); + throw new RuntimeException("Duplicate workflows"); + } else { + return workflows.iterator().next(); + } } catch (PersistenceException e) { throw new RuntimeException(e); } http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js index dcfba34..62d3be3 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js @@ -24,6 +24,7 @@ const Validations = buildValidations({ }); export default Ember.Component.extend(Validations, { + assetManager : Ember.inject.service('asset-manager'), initialize: function(){ this.$('#asset_config_dialog').modal('show'); this.$('#asset_config_dialog').modal().on('hidden.bs.modal', function() { @@ -39,8 +40,21 @@ export default Ember.Component.extend(Validations, { this.set('showErrorMessage', true); return; } - this.$('#asset_config_dialog').modal('hide'); - this.sendAction('saveAssetConfig'); + this.set("inProgress", true); + var assetNameAvailableDefered=this.get("assetManager").assetNameAvailable(this.get("assetModel.name")); + assetNameAvailableDefered.promise.then(function(data){ + this.set("inProgress", false); + if (data === "false") { + this.set("assetErrorMsg", "Asset name already exists"); + return; + } else { + this.$('#asset_config_dialog').modal('hide'); + this.sendAction('saveAssetConfig'); + } + }.bind(this)).catch(function(data){ + model.set("inProgress", false); + return "There is some problem while checking asset name availability. Please try again."; + }); } } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js index 9ad0494..ae695fe 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js @@ -17,9 +17,11 @@ import Ember from 'ember'; export default Ember.Component.extend({ + assetManager : Ember.inject.service('asset-manager'), currentAssetId: null, assetNotSelected: true, assetSearchCriteria: "", + filteredAssetList: Ember.A([]), fuseSearchOptions: { shouldSort: true, threshold: 0.1, @@ -46,7 +48,23 @@ export default Ember.Component.extend({ this.$('#asset_list_dialog').modal().on('hidden.bs.modal', function() { this.sendAction('showAssetList', false); }.bind(this)); - this.initializeFuseSearch(); + + self.set("inProgress", true); + self.set("assetErrorMsg", ""); + var fetchAssetsDefered=self.get("assetManager").fetchAssets(); + fetchAssetsDefered.promise.then(function(response){ + var assetData = JSON.parse(response).data; + if (self.get("assetListType") && self.get("assetListType") !== "") { + assetData = assetData.filterBy('type', self.get("assetListType")); + } + self.set('assetList', assetData); + self.initializeFuseSearch(); + self.set("inProgress", false); + }.bind(this)).catch(function(data){ + self.set("assetErrorMsg", "There is some problem while fetching assets. Please try again."); + self.set("inProgress", false); + }); + }.on('didInsertElement'), initializeFuseSearch() { this.set('fuse', new Fuse(this.get("assetList"), this.get('fuseSearchOptions'))); http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js index 4674533..5228324 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js @@ -17,7 +17,10 @@ import Ember from 'ember'; export default Ember.Component.extend({ + assetManager : Ember.inject.service('asset-manager'), assetSearchCriteria: "", + currentAsset: null, + filteredAssetList: Ember.A([]), fuseSearchOptions: { shouldSort: true, threshold: 0.1, @@ -45,7 +48,17 @@ export default Ember.Component.extend({ this.sendAction('showAssetManager', false); }.bind(this)); - this.initializeFuseSearch(); + self.set("inProgress", true); + self.set("errorMsg", ""); + var fetchAssetsDefered=self.get("assetManager").fetchMyAssets(); + fetchAssetsDefered.promise.then(function(response){ + self.set('assetList', JSON.parse(response).data); + self.initializeFuseSearch(); + self.set("inProgress", false); + }.bind(this)).catch(function(data){ + self.set("errorMsg", "There is some problem while fetching assets. Please try again."); + self.set("inProgress", false); + }); }.on('didInsertElement'), initializeFuseSearch() { this.set('fuse', new Fuse(this.get("assetList"), this.get('fuseSearchOptions'))); @@ -62,9 +75,39 @@ export default Ember.Component.extend({ close() { this.$('#asset_manager_dialog').modal('hide'); }, - deleteAsset(asset) { - this.$('#asset_manager_dialog').modal('hide'); - this.sendAction('deleteAsset', asset); + deleteAsset() { + var self=this; + self.set("inProgress", true); + self.set("errorMsg", ""); + self.set("successMsg", ""); + var deleteAssetDefered=self.get("assetManager").deleteAsset(self.get("currentAsset").id); + deleteAssetDefered.promise.then(function(response){ + var fetchAssetsDefered=self.get("assetManager").fetchMyAssets(); + fetchAssetsDefered.promise.then(function(response){ + self.get("assetList").clear(); + self.get("assetList").pushObjects(JSON.parse(response).data); + if (self.get("assetSearchCriteria") !== "") { + self.set('filteredAssetList', self.get('fuse').search(self.get("assetSearchCriteria"))); + } else { + self.set('filteredAssetList', self.get("assetList")); + } + self.set("successMsg", "Asset got deleted successfully"); + self.set("inProgress", false); + }.bind(this)).catch(function(data){ + self.set("errorMsg", "There is some problem while fetching assets. Please try again."); + self.set("inProgress", false); + }); + }.bind(this)).catch(function(data){ + self.set("errorMsg", "There is some problem while deleting asset. Please try again."); + self.set("inProgress", false); + }); + }, + showDeleteAssetWarning(asset) { + this.set("currentAsset", asset); + this.set('showingDeleteAssetWarning', true); + Ember.run.later(()=>{ + this.$('#ConfirmDialog').modal('show'); + }); } } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js index a04c66d..422253d 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js @@ -19,7 +19,6 @@ import CommonUtils from "../utils/common-utils"; import Constants from '../utils/constants'; export default Ember.Component.extend({ workspaceManager : Ember.inject.service('workspace-manager'), - assetManager : Ember.inject.service('asset-manager'), xmlAppPath : null, appPath : null, type : 'wf', @@ -236,27 +235,7 @@ export default Ember.Component.extend({ } }, showAssetManager(value) { - var self=this; - if (value) { - var fetchAssetsDefered=self.get("assetManager").fetchMyAssets(); - fetchAssetsDefered.promise.then(function(response){ - self.set('assetList', JSON.parse(response).data); - self.set('showingAssetManager', value); - }.bind(this)).catch(function(data){ - self.set("errorMsg", "There is some problem while fetching assets. Please try again."); - }); - } else { - self.set('showingAssetManager', value); - } - }, - deleteAsset(asset) { - var self=this; - var deleteAssetDefered=self.get("assetManager").deleteAsset(asset.id); - deleteAssetDefered.promise.then(function(response){ - console.log("Asset deleted.."); - }.bind(this)).catch(function(data){ - self.set("errorMsg", "There is some problem while deleting asset. Please try again."); - }); + this.set('showingAssetManager', value); } } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js index 1822a20..c682ea9 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js @@ -349,6 +349,24 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { }); return deferred; }, + getAssetFromHdfs(filePath){ + var url = Ember.ENV.API_URL + "/readAsset?assetPath="+filePath; + var deferred = Ember.RSVP.defer(); + Ember.$.ajax({ + url: url, + method: 'GET', + dataType: "text", + beforeSend: function (xhr) { + xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + xhr.setRequestHeader("X-Requested-By", "Ambari"); + } + }).done(function(data){ + deferred.resolve(data); + }).fail(function(data){ + deferred.reject(data); + }); + return deferred; + }, importActionSettingsFromString(actionSettings) { var x2js = new X2JS(); var actionSettingsObj = x2js.xml_str2json(actionSettings); @@ -945,13 +963,13 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { this.set("showingActionSettingsFileBrowser", false); if(this.get('actionSettingsFilePath')){ self.set("errorMsg", ""); - var actionSettingsXmlDefered=this.getWorkflowFromHdfs(this.get('actionSettingsFilePath')); + var actionSettingsXmlDefered=this.getAssetFromHdfs(this.get('actionSettingsFilePath')); actionSettingsXmlDefered.promise.then(function(data){ this.importActionSettingsFromString(data); }.bind(this)).catch(function(data){ console.error(data); var stackTraceMsg = self.getStackTrace(data.responseText); - self.set("errorMsg", "There is some problem while importing.Please try again."); + self.set("errorMsg", "There is some problem while importing asset.Please try again."); self.showingErrorMsgInDesigner(data); }); } @@ -964,13 +982,13 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { this.set("showingImportActionNodeFileBrowser", false); if(this.get('actionNodeFilePath')){ self.set("errorMsg", ""); - var actionSettingsXmlDefered=this.getWorkflowFromHdfs(this.get('actionNodeFilePath')); + var actionSettingsXmlDefered=this.getAssetFromHdfs(this.get('actionNodeFilePath')); actionSettingsXmlDefered.promise.then(function(data){ this.importActionNodeFromString(data); }.bind(this)).catch(function(data){ console.error(data); var stackTraceMsg = self.getStackTrace(data.responseText); - self.set("errorMsg", "There is some problem while importing.Please try again."); + self.set("errorMsg", "There is some problem while importing asset. Please try again."); self.showingErrorMsgInDesigner(data); }); } @@ -1109,22 +1127,8 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { }, showAssetList(value) { var self=this; - if (value) { - self.set("errorMsg", ""); - var fetchAssetsDefered=self.get("assetManager").fetchAssets(); - fetchAssetsDefered.promise.then(function(response){ - var assetData = JSON.parse(response).data; - assetData = assetData.filterBy('type', self.flowRenderer.currentCyNode.data().node.actionType); - self.set('assetList', assetData); - self.set('assetListType', self.flowRenderer.currentCyNode.data().node.actionType); - self.set('showingAssetList', value); - }.bind(this)).catch(function(data){ - self.set("errorMsg", "There is some problem while fetching assets. Please try again."); - self.showingErrorMsgInDesigner(data); - }); - } else { - self.set('showingAssetList', value); - } + self.set('showingAssetList', value); + self.set('assetListType', self.flowRenderer.currentCyNode.data().node.actionType); }, importAsset(asset) { var self=this; @@ -1143,19 +1147,8 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { }, showAssetNodeList(value) { var self=this; - if (value) { - self.set("errorMsg", ""); - var fetchAssetsDefered=self.get("assetManager").fetchAssets(); - fetchAssetsDefered.promise.then(function(response){ - self.set('assetList', JSON.parse(response).data); - self.set('showingAssetNodeList', value); - }.bind(this)).catch(function(data){ - self.set("errorMsg", "There is some problem while fetching assets. Please try again."); - self.showingErrorMsgInDesigner(data); - }); - } else { - self.set('showingAssetNodeList', value); - } + self.set('showingAssetNodeList', value); + self.set('assetListType', ""); }, importAssetNode(asset) { var self=this; http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js b/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js index 3e87644..45f99e7 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js @@ -138,5 +138,24 @@ export default Ember.Service.extend({ deferred.reject(data); }); return deferred; + }, + assetNameAvailable(assetName) { + var url = Ember.ENV.API_URL + "/assets/assetNameAvailable?name=" + assetName; + var deferred = Ember.RSVP.defer(); + Ember.$.ajax({ + url: url, + method: "GET", + dataType: "text", + contentType: "text/plain;charset=utf-8", + beforeSend: function (xhr) { + xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + xhr.setRequestHeader("X-Requested-By", "workflow-designer"); + } + }).done(function(data){ + deferred.resolve(data); + }).fail(function(data){ + deferred.reject(data); + }); + return deferred; } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less index d91eb3b..755a6ad 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less +++ b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less @@ -1636,3 +1636,7 @@ input:invalid { width: 100%; min-height: 175px; } +#asset-delete-confirm-dialog .modal-dialog{ + width: 650px; + top: 60px; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs index 3ae4bff..7bc48d7 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs +++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs @@ -25,6 +25,11 @@ <h4 class="modal-title">Publish Asset</h4> </div> <div class="modal-body"> + {{#if (and assetErrorMsg (not (eq assetErrorMsg "")))}} + <div id="alert"class="alert alert-danger alert-dismissible" role="alert"> + {{assetErrorMsg}} + </div> + {{/if}} <form class="form-horizontal"> <div class="panel panel-default"> <div class="panel-body"> @@ -52,3 +57,6 @@ </div> </div> </div> +{{#if inProgress}} + {{spin-spinner lines=13 length=20 width=10 top=200}} +{{/if}} http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs index bc5201d..7fd1236 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs +++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs @@ -26,6 +26,11 @@ </div> <div class="modal-body"> {{input type="text" class="form-control marginBottom10" name="assetSearchCriteria" value=assetSearchCriteria placeholder="Asset Search"}} + {{#if (and assetErrorMsg (not (eq assetErrorMsg "")))}} + <div id="alert"class="alert alert-danger alert-dismissible" role="alert"> + {{assetErrorMsg}} + </div> + {{/if}} <div class="panel panel-default mb0 asset-list-panel-header"> <table class="table asset-list-header-table listing table-striped table-hover table-bordered" cellspacing="0" width="100%"> <thead> @@ -38,8 +43,8 @@ </thead> </table> </div> - <div class="panel panel-default asset-list-panel-body {{if (eq filteredAssetList.length 0) 'no-asset-records'}}"> - {{#if (eq filteredAssetList.length 0)}} + <div class="panel panel-default asset-list-panel-body {{if (and (eq filteredAssetList.length 0) (eq assetErrorMsg "")) 'no-asset-records'}}"> + {{#if (and (eq filteredAssetList.length 0) (eq assetErrorMsg ""))}} No {{#if (not-eq assetListType "")}} {{assetListType}}{{/if}} assets {{/if}} <table id="asset-list" class="table asset-list listing table-striped table-hover table-bordered" cellspacing="0" width="100%"> @@ -64,3 +69,6 @@ </div> </div> </div> +{{#if inProgress}} + {{spin-spinner lines=13 length=20 width=10 top=200}} +{{/if}} http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs index 7a21af1..6ca85c6 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs +++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs @@ -26,6 +26,16 @@ </div> <div class="modal-body"> {{input type="text" class="form-control marginBottom10" name="assetSearchCriteria" value=assetSearchCriteria placeholder="Asset Search"}} + {{#if (and errorMsg (not (eq errorMsg "")))}} + <div id="alert"class="alert alert-danger alert-dismissible" role="alert"> + {{errorMsg}} + </div> + {{/if}} + {{#if (and successMsg (not (eq successMsg "")))}} + <div id="alert"class="alert alert-success alert-dismissible" role="alert"> + {{successMsg}} + </div> + {{/if}} <div class="panel panel-default mb0 asset-list-panel-header"> <table class="table asset-list-header-table listing table-striped table-hover table-bordered" cellspacing="0" width="100%"> <thead> @@ -38,8 +48,8 @@ </thead> </table> </div> - <div class="panel panel-default asset-list-panel-body {{if (eq filteredAssetList.length 0) 'no-asset-records'}}"> - {{#if (eq filteredAssetList.length 0)}} + <div class="panel panel-default asset-list-panel-body {{if (and (eq filteredAssetList.length 0) (eq errorMsg "")) 'no-asset-records'}}"> + {{#if (and (eq filteredAssetList.length 0) (eq errorMsg ""))}} <span>No assets</span> {{/if}} <table id="asset-list" class="table asset-list listing table-striped table-hover table-bordered" cellspacing="0" width="100%"> @@ -49,7 +59,7 @@ <td class="col-xs-3">{{asset.name}}</td> <td class="col-xs-3">{{asset.type}}</td> <td class="col-xs-3">{{asset.description}}</td> - <td class="col-xs-3"><span {{action 'deleteAsset' asset}}><i class="fa fa-trash-o"></i></span></td> + <td class="col-xs-3"><span {{action 'showDeleteAssetWarning' asset}}><i class="fa fa-trash-o"></i></span></td> </tr> {{/each}} </tbody> @@ -63,3 +73,13 @@ </div> </div> </div> +{{#if showingDeleteAssetWarning}} + <div id="asset-delete-confirm-dialog"> + {{#confirmation-dialog title="Confirm asset delete" + confirmationMessage="Do you want to delete this asset ?" + okBtnText="Continue" cancelBtnText="Cancel" onOk="deleteAsset"}}{{/confirmation-dialog}} + </div> +{{/if}} +{{#if inProgress}} + {{spin-spinner lines=13 length=20 width=10 top=200}} +{{/if}} http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs index 7a6005a..46a3f63 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs +++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs @@ -126,7 +126,7 @@ </div> </div> {{#if showingAssetManager}} - {{#asset-manager showAssetManager="showAssetManager" deleteAsset="deleteAsset" assetList=assetList}}{{/asset-manager}} + {{#asset-manager showAssetManager="showAssetManager"}}{{/asset-manager}} {{/if}} {{#if showingWarning}} {{#confirmation-dialog title="Confirm workflow reset" http://git-wip-us.apache.org/repos/asf/ambari/blob/74aff7c6/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs index 38d8eaf..1758946 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs +++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs @@ -201,7 +201,7 @@ </div> {{/if}} {{/each}} - <div class="overlay-node-label">asd</div> + <div class="overlay-node-label"></div> <div class="overlay-transition-content"> <div class="decision-condition-label"> <div class="decision-condition-header">Condition</div> @@ -306,7 +306,7 @@ {{#asset-list showAssetList="showAssetList" importAsset="importAsset" assetList=assetList assetListType=assetListType}}{{/asset-list}} {{/if}} {{#if showingAssetNodeList}} - {{#asset-list showAssetList="showAssetNodeList" importAsset="importAssetNode" deleteAsset="deleteAsset" assetList=assetList}}{{/asset-list}} + {{#asset-list showAssetList="showAssetNodeList" importAsset="importAssetNode" assetList=assetList}}{{/asset-list}} {{/if}} {{#if showingPreview}} {{#preview-dialog title="Workflow XML Preview" previewXml=previewXml closePreview="closePreview"}}{{/preview-dialog}}