You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2014/11/26 17:40:34 UTC
[1/2] ambari git commit: AMBARI-8403. Views: Files download of ZIP
fails on folder with no permissions (alexantonenko)
Repository: ambari
Updated Branches:
refs/heads/trunk 7b7f0c92b -> 9218a8ebf
AMBARI-8403. Views: Files download of ZIP fails on folder with no permissions (alexantonenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/a6127158
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/a6127158
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/a6127158
Branch: refs/heads/trunk
Commit: a61271583c7bd85f5c1b3cf537cdcce2a461e0a1
Parents: 7b7f0c9
Author: Alex Antonenko <hi...@gmail.com>
Authored: Wed Nov 26 17:43:36 2014 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Wed Nov 26 18:40:08 2014 +0200
----------------------------------------------------------------------
contrib/views/files/pom.xml | 1 -
.../view/filebrowser/DownloadService.java | 47 ++++++++++++++------
.../view/filebrowser/FileOperationService.java | 10 ++---
.../apache/ambari/view/filebrowser/HdfsApi.java | 32 +++++++++++--
.../ambari/view/filebrowser/HdfsService.java | 8 ++--
.../ambari/view/filebrowser/HelpService.java | 6 +--
.../ambari/view/filebrowser/UploadService.java | 4 +-
.../files/src/main/resources/ui/app/adapter.js | 30 ++++++-------
.../main/resources/ui/app/controllers/file.js | 26 +++++++----
.../main/resources/ui/app/controllers/files.js | 40 ++++++++++-------
.../src/main/resources/ui/app/models/file.js | 23 +++++-----
.../ui/app/templates/components/contextMenu.hbs | 4 +-
.../main/resources/ui/app/templates/files.hbs | 6 +--
.../resources/ui/app/templates/util/fileRow.hbs | 12 ++---
.../files/src/main/resources/ui/bower.json | 8 +---
.../files/src/main/resources/ui/config.coffee | 15 ++++---
.../files/src/main/resources/ui/package.json | 4 +-
contrib/views/files/src/main/resources/view.xml | 10 ++---
.../view/filebrowser/FilebrowserTest.java | 4 +-
19 files changed, 177 insertions(+), 113 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/files/pom.xml b/contrib/views/files/pom.xml
index dd8325e..7813712 100644
--- a/contrib/views/files/pom.xml
+++ b/contrib/views/files/pom.xml
@@ -177,7 +177,6 @@
<arguments>
<argument>node_modules/.bin/brunch</argument>
<argument>build</argument>
- <argument>--production</argument>
</arguments>
</configuration>
</execution>
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/DownloadService.java
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/DownloadService.java b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/DownloadService.java
index 72ba726..063d453 100644
--- a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/DownloadService.java
+++ b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/DownloadService.java
@@ -51,6 +51,7 @@ import org.apache.ambari.view.filebrowser.utils.ServiceFormattedException;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.ambari.view.ViewContext;
+import org.apache.hadoop.security.AccessControlException;
import org.json.simple.JSONObject;
//import org.glassfish.jersey.server.ChunkedOutput;
@@ -100,34 +101,44 @@ public class DownloadService extends HdfsService {
}
}
- private void zipFile(ZipOutputStream zip, String path) throws InterruptedException, IOException {
+ private void zipFile(ZipOutputStream zip, String path) {
try {
- zip.putNextEntry(new ZipEntry(path.substring(1)));
FSDataInputStream in = getApi(context).open(path);
+ zip.putNextEntry(new ZipEntry(path.substring(1)));
byte[] chunk = new byte[1024];
while (in.read(chunk) != -1) {
zip.write(chunk);
}
} catch (IOException ex) {
- String msg = "Error zipping file " + path.substring(1) + ": "
+ logger.error("Error zipping file " + path.substring(1) + " (file ignored): "
+ + ex.getMessage());
+ } catch (InterruptedException ex) {
+ String msg = "Error zipping file " + path.substring(1) + " (file ignored): "
+ ex.getMessage();
logger.error(msg);
- zip.write(ex.getMessage().getBytes());
- throw new ServiceFormattedException(ex.getMessage(), ex);
} finally {
- zip.closeEntry();
+ try {
+ zip.closeEntry();
+ } catch (IOException ex) {
+ logger.error("Error closing entry " + path.substring(1) + " (file ignored): "
+ + ex.getMessage());
+ }
}
}
private void zipDirectory(ZipOutputStream zip, String path) {
try {
zip.putNextEntry(new ZipEntry(path.substring(1) + "/"));
- zip.closeEntry();
} catch (IOException ex) {
- String msg = "Error zipping directory " + path.substring(1) + "/" + ": "
- + ex.getMessage();
- logger.error(msg);
- throw new ServiceFormattedException(msg, ex);
+ logger.error("Error zipping directory " + path.substring(1) + "/ (directory ignored)" + ": "
+ + ex.getMessage());
+ } finally {
+ try {
+ zip.closeEntry();
+ } catch (IOException ex) {
+ logger.error("Error zipping directory " + path.substring(1) + "/ (directory ignored)" + ": "
+ + ex.getMessage());
+ }
}
}
@@ -156,7 +167,14 @@ public class DownloadService extends HdfsService {
String path = files.poll();
FileStatus status = api.getFileStatus(path);
if (status.isDirectory()) {
- FileStatus[] subdir = api.listdir(path);
+ FileStatus[] subdir;
+ try {
+ subdir = api.listdir(path);
+ } catch (AccessControlException ex) {
+ logger.error("Error zipping directory " + path.substring(1) + "/ (directory ignored)" + ": "
+ + ex.getMessage());
+ continue;
+ }
for (FileStatus file : subdir) {
files.add(org.apache.hadoop.fs.Path
.getPathWithoutSchemeAndAuthority(file.getPath())
@@ -240,10 +258,13 @@ public class DownloadService extends HdfsService {
@GET
@Path("/zip")
@Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_OCTET_STREAM)
+ @Produces("application/zip")
public Response zipByRequestId(@QueryParam("requestId") String requestId) {
try {
String json = context.getInstanceData(requestId);
+ if (json == null) {
+ throw new NotFoundFormattedException("Request is old", null);
+ }
DownloadRequest request = gson.fromJson(json, DownloadRequest.class);
context.removeInstanceData(requestId);
return downloadGZip(request);
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/FileOperationService.java
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/FileOperationService.java b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/FileOperationService.java
index d043917..444899f 100644
--- a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/FileOperationService.java
+++ b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/FileOperationService.java
@@ -58,7 +58,7 @@ public class FileOperationService extends HdfsService {
public Response listdir(@QueryParam("path") String path) {
try {
return Response.ok(
- HdfsApi.fileStatusToJSON(getApi(context).listdir(path))).build();
+ getApi(context).fileStatusToJSON(getApi(context).listdir(path))).build();
} catch (WebApplicationException ex) {
throw ex;
} catch (FileNotFoundException ex) {
@@ -82,7 +82,7 @@ public class FileOperationService extends HdfsService {
HdfsApi api = getApi(context);
ResponseBuilder result;
if (api.rename(request.src, request.dst)) {
- result = Response.ok(HdfsApi.fileStatusToJSON(api
+ result = Response.ok(getApi(context).fileStatusToJSON(api
.getFileStatus(request.dst)));
} else {
result = Response.ok(new BoolResult(false)).status(422);
@@ -109,7 +109,7 @@ public class FileOperationService extends HdfsService {
HdfsApi api = getApi(context);
ResponseBuilder result;
if (api.chmod(request.path, request.mode)) {
- result = Response.ok(HdfsApi.fileStatusToJSON(api
+ result = Response.ok(getApi(context).fileStatusToJSON(api
.getFileStatus(request.path)));
} else {
result = Response.ok(new BoolResult(false)).status(422);
@@ -137,7 +137,7 @@ public class FileOperationService extends HdfsService {
HdfsApi api = getApi(context);
ResponseBuilder result;
if (api.copy(request.src, request.dst)) {
- result = Response.ok(HdfsApi.fileStatusToJSON(api
+ result = Response.ok(getApi(context).fileStatusToJSON(api
.getFileStatus(request.dst)));
} else {
result = Response.ok(new BoolResult(false)).status(422);
@@ -163,7 +163,7 @@ public class FileOperationService extends HdfsService {
HdfsApi api = getApi(context);
ResponseBuilder result;
if (api.mkdir(request.path)) {
- result = Response.ok(HdfsApi.fileStatusToJSON(api.getFileStatus(request.path)));
+ result = Response.ok(getApi(context).fileStatusToJSON(api.getFileStatus(request.path)));
} else {
result = Response.ok(new BoolResult(false)).status(422);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsApi.java
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsApi.java b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsApi.java
index cd88c54..fcc4d16 100644
--- a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsApi.java
+++ b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsApi.java
@@ -20,12 +20,16 @@ package org.apache.ambari.view.filebrowser;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
+import org.apache.hadoop.fs.permission.AccessControlException;
+import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import org.apache.hadoop.security.UserGroupInformation;
@@ -261,7 +265,7 @@ public class HdfsApi {
return ugi.doAs(new PrivilegedExceptionAction<Boolean>() {
public Boolean run() throws Exception {
try {
- fs.setPermission(new Path(path), new FsPermission(permissions));
+ fs.setPermission(new Path(path), FsPermission.valueOf(permissions));
} catch (Exception ex) {
return false;
}
@@ -313,7 +317,7 @@ public class HdfsApi {
* @return The JSON representation of the file status.
*/
- public static Map<String, Object> fileStatusToJSON(FileStatus status) {
+ public Map<String, Object> fileStatusToJSON(FileStatus status) {
Map<String, Object> json = new LinkedHashMap<String, Object>();
json.put("path", Path.getPathWithoutSchemeAndAuthority(status.getPath())
.toString());
@@ -327,6 +331,9 @@ public class HdfsApi {
json.put("modificationTime", status.getModificationTime());
json.put("blockSize", status.getBlockSize());
json.put("replication", status.getReplication());
+ json.put("readAccess", checkAccessPermissions(status, FsAction.READ, ugi));
+ json.put("writeAccess", checkAccessPermissions(status, FsAction.WRITE, ugi));
+ json.put("executeAccess", checkAccessPermissions(status, FsAction.EXECUTE, ugi));
return json;
}
@@ -341,7 +348,7 @@ public class HdfsApi {
* @return The JSON representation of the file status array.
*/
@SuppressWarnings("unchecked")
- public static JSONArray fileStatusToJSON(FileStatus[] status) {
+ public JSONArray fileStatusToJSON(FileStatus[] status) {
JSONArray json = new JSONArray();
if (status != null) {
for (FileStatus s : status) {
@@ -351,4 +358,23 @@ public class HdfsApi {
return json;
}
+ public static boolean checkAccessPermissions(FileStatus stat, FsAction mode, UserGroupInformation ugi) {
+ FsPermission perm = stat.getPermission();
+ String user = ugi.getShortUserName();
+ List<String> groups = Arrays.asList(ugi.getGroupNames());
+ if (user.equals(stat.getOwner())) {
+ if (perm.getUserAction().implies(mode)) {
+ return true;
+ }
+ } else if (groups.contains(stat.getGroup())) {
+ if (perm.getGroupAction().implies(mode)) {
+ return true;
+ }
+ } else {
+ if (perm.getOtherAction().implies(mode)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsService.java
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsService.java b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsService.java
index 06f27b0..1fd5719 100644
--- a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsService.java
+++ b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HdfsService.java
@@ -64,13 +64,13 @@ public abstract class HdfsService {
public HdfsApi getApi(ViewContext context) {
if (_api == null) {
Thread.currentThread().setContextClassLoader(null);
- String defaultFs = context.getProperties().get("dataworker.defaultFs");
+ String defaultFs = context.getProperties().get("webhdfs.url");
if (defaultFs == null)
- throw new MisconfigurationFormattedException("dataworker.defaultFs");
+ throw new MisconfigurationFormattedException("webhdfs.url");
try {
_api = new HdfsApi(defaultFs, getUsername(context));
} catch (Exception ex) {
- throw new ServiceFormattedException("HdfsApi connection failed. Check \"dataworker.defaultFs\" property", ex);
+ throw new ServiceFormattedException("HdfsApi connection failed. Check \"webhdfs.url\" property", ex);
}
}
return _api;
@@ -82,7 +82,7 @@ public abstract class HdfsService {
* @return user name
*/
public String getUsername(ViewContext context) {
- String username = context.getProperties().get("dataworker.username");
+ String username = context.getProperties().get("webhdfs.username");
if (username == null || username.isEmpty())
username = context.getUsername();
return username;
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HelpService.java
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HelpService.java b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HelpService.java
index d12c47c..695ca38 100644
--- a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HelpService.java
+++ b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/HelpService.java
@@ -75,7 +75,7 @@ public class HelpService extends HdfsService {
@Produces(MediaType.TEXT_PLAIN)
public Response filesystem() {
return Response.ok(
- context.getProperties().get("dataworker.defaultFs")).build();
+ context.getProperties().get("webhdfs.url")).build();
}
/**
@@ -89,7 +89,7 @@ public class HelpService extends HdfsService {
try {
HdfsApi api = getApi(context);
return Response
- .ok(HdfsApi.fileStatusToJSON(api.getFileStatus(api.getHomeDir()
+ .ok(getApi(context).fileStatusToJSON(api.getFileStatus(api.getHomeDir()
.toString()))).build();
} catch (WebApplicationException ex) {
throw ex;
@@ -127,7 +127,7 @@ public class HelpService extends HdfsService {
try {
HdfsApi api = getApi(context);
return Response.ok(
- HdfsApi.fileStatusToJSON(api.getFileStatus(api.getTrashDir()
+ getApi(context).fileStatusToJSON(api.getFileStatus(api.getTrashDir()
.toString()))).build();
} catch (WebApplicationException ex) {
throw ex;
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/UploadService.java
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/UploadService.java b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/UploadService.java
index 1ff5571..051bdfb 100644
--- a/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/UploadService.java
+++ b/contrib/views/files/src/main/java/org/apache/ambari/view/filebrowser/UploadService.java
@@ -77,7 +77,7 @@ public class UploadService extends HdfsService {
String filePath = path + contentDisposition.getFileName();
uploadFile(filePath, uploadedInputStream);
return Response.ok(
- HdfsApi.fileStatusToJSON(getApi(context).getFileStatus(filePath)))
+ getApi(context).fileStatusToJSON(getApi(context).getFileStatus(filePath)))
.build();
} catch (WebApplicationException ex) {
throw ex;
@@ -118,7 +118,7 @@ public class UploadService extends HdfsService {
}
ze = zip.getNextEntry();
}
- return Response.ok(HdfsApi.fileStatusToJSON(api.listdir(path))).build();
+ return Response.ok(getApi(context).fileStatusToJSON(api.listdir(path))).build();
} catch (WebApplicationException ex) {
throw ex;
} catch (Exception ex) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/app/adapter.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/adapter.js b/contrib/views/files/src/main/resources/ui/app/adapter.js
index a6e471f..ff98a10 100644
--- a/contrib/views/files/src/main/resources/ui/app/adapter.js
+++ b/contrib/views/files/src/main/resources/ui/app/adapter.js
@@ -147,11 +147,10 @@ function getNamespaceUrl() {
instance = parts[2];
version = '';
}
- var namespaceUrl = 'api/v1/views' + view + version + '/instances' + instance + '/';
- return namespaceUrl;
+ return 'api/v1/views' + view + version + '/instances' + instance + '/';
}
-App.Store = DS.Store.extend({
+App.ApplicationStore = DS.Store.extend({
adapter: DS.RESTAdapter.extend({
namespace: getNamespaceUrl() + 'resources/files',
headers: {
@@ -252,24 +251,25 @@ App.Store = DS.Store.extend({
},
/**
* get dowload link
- * @param {Array} file records for download
+ * @param {Array} files records for download
* @param {String} option browse, zip or concat
* @param {Boolean} download
* @return {Promise}
*/
linkFor:function (files, option, download) {
- var resolver = Ember.RSVP.defer('promiseLabel');
- var adapter = this.adapterFor(this.modelFor('file')),
- download = download || true;
- option = option || "browse";
+ var resolver = Ember.RSVP.defer('promiseLabel'),
+ adapter = this.adapterFor(this.modelFor('file')),
+ query = {},
+ download = download || true;
+ option = option || "browse";
if (option == 'browse') {
- var query = { "path": files.get('firstObject.path'), "download": download };
- resolver.resolve(adapter.downloadUrl('browse',query))
+ query = { "path": files.get('firstObject.path'), "download": download };
+ resolver.resolve(adapter.downloadUrl('browse',query));
return resolver.promise;
- };
+ }
- var query = {
+ query = {
"entries": [],
"download": download
};
@@ -278,7 +278,7 @@ App.Store = DS.Store.extend({
query.entries.push(item.get('path'));
});
- resolver.resolve(adapter.linkFor(option, query))
+ resolver.resolve(adapter.linkFor(option, query));
return resolver.promise.then(function(response) {
return adapter.downloadUrl(option,response);
@@ -286,7 +286,7 @@ App.Store = DS.Store.extend({
throw reason;
});
}
-})
+});
App.FileSerializer = DS.RESTSerializer.extend({
primaryKey:'path',
@@ -300,7 +300,7 @@ App.FileSerializer = DS.RESTSerializer.extend({
},
extractChmod:function(store, type, payload, id, requestType) {
return this.extractSingle(store, type, payload, id, requestType);
- },
+ }
});
App.Uploader = Ember.Uploader.create({
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/app/controllers/file.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/controllers/file.js b/contrib/views/files/src/main/resources/ui/app/controllers/file.js
index f8b7046..7992814 100644
--- a/contrib/views/files/src/main/resources/ui/app/controllers/file.js
+++ b/contrib/views/files/src/main/resources/ui/app/controllers/file.js
@@ -25,9 +25,11 @@ App.FileController = Ember.ObjectController.extend({
},
actions:{
download:function (option) {
- this.store.linkFor([this.get('content')],option).then(function (link) {
- window.location.href = link;
- },Em.run.bind(this,this.sendAlert));
+ if (this.get('content.readAccess')) {
+ this.store.linkFor([this.get('content')],option).then(function (link) {
+ window.location.href = link;
+ },Em.run.bind(this,this.sendAlert));
+ }
},
showChmod:function () {
this.toggleProperty('chmodVisible',true);
@@ -56,17 +58,20 @@ App.FileController = Ember.ObjectController.extend({
.then(null,Em.run.bind(this,this.chmodErrorCallback,record));
},
open:function (file) {
+ if (!this.get('content.readAccess')) {
+ return false;
+ }
if (this.get('content.isDirectory')) {
return this.transitionToRoute('files',{queryParams: {path: this.get('content.id')}});
} else{
return this.send('download');
- };
+ }
},
deleteFile:function (deleteForever) {
this.store
.remove(this.get('content'),!deleteForever)
- .then(null,Em.run.bind(this,this.sendAlert));
- },
+ .then(null,Em.run.bind(this,this.deleteErrorCallback,this.get('content')));
+ }
},
selected:false,
isRenaming:false,
@@ -95,10 +100,15 @@ App.FileController = Ember.ObjectController.extend({
chmodErrorCallback:function (record,error) {
record.rollback();
- this.sendAlert(error);
+ this.sendAlert({message:'Permissions change failed'});
},
- sendAlert:function (error) {
+ deleteErrorCallback:function (record,error) {
+ this.parentController.model.pushRecord(record);
this.send('showAlert',error);
},
+
+ sendAlert:function (error) {
+ this.send('showAlert',error);
+ }
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/app/controllers/files.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/controllers/files.js b/contrib/views/files/src/main/resources/ui/app/controllers/files.js
index a9d98e8..8de6a4b 100644
--- a/contrib/views/files/src/main/resources/ui/app/controllers/files.js
+++ b/contrib/views/files/src/main/resources/ui/app/controllers/files.js
@@ -22,36 +22,35 @@ var bind = Ember.run.bind;
App.FilesController = Ember.ArrayController.extend({
actions:{
moveFile:function (opt,file) {
- var src, title,
- file = file || this.get('selectedFiles.firstObject'),
+ var src,
moving = this.get('movingFile');
-
+ file = file || this.get('selectedFiles.firstObject');
if (opt == 'cut') {
src = file.toJSON({includeId: true});
- src = Em.merge(src,{name:file.get('name'),path:file.get('path')})
+ src = Em.merge(src,{name:file.get('name'),path:file.get('path')});
this.set('movingFile',src);
- };
+ }
if (opt == 'move') {
this.store.move(moving.path,[this.get('path'),moving.name].join('/').replace('//','/'))
.then(bind(this,this.set,'movingFile',null),bind(this,this.throwAlert));
- };
+ }
if (opt == 'cancel') {
this.set('movingFile',null);
- };
+ }
},
showRenameInput:function () {
this.toggleProperty('isRenaming');
},
renameDir:function (path,newName) {
var _this = this,
- basedir = path.substring(0,path.lastIndexOf('/')+1);
+ basedir = path.substring(0,path.lastIndexOf('/')+1),
newPath = basedir + newName;
if (path === newPath) {
return false;
- };
+ }
this.store.listdir(basedir).then(function (listdir) {
var recordExists = listdir.isAny('id',newPath);
@@ -62,14 +61,14 @@ App.FilesController = Ember.ArrayController.extend({
if (recordExists) {
return _this.throwAlert({message:newPath + ' already exists.'});
- };
+ }
return _this.store.move(path,newPath);
}).then(function (newDir) {
if (newDir) {
_this.store.unloadRecord(newDir);
_this.set('path',newPath);
- };
+ }
}).catch(bind(this,this.throwAlert));
},
@@ -78,11 +77,11 @@ App.FilesController = Ember.ArrayController.extend({
var selected = this.get('selectedFiles');
var moveToTrash = !deleteForever;
selected.forEach(function (file) {
- self.store.remove(file,moveToTrash).then(null,bind(self,self.throwAlert));
+ self.store.remove(file,moveToTrash).then(null,bind(self,self.deleteErrorCallback,file));
});
},
download:function (option) {
- var files = this.get('selectedFiles');
+ var files = this.get('selectedFiles').filterBy('readAccess',true);
this.store.linkFor(files,option).then(function (link) {
window.location.href = link;
});
@@ -94,11 +93,11 @@ App.FilesController = Ember.ArrayController.extend({
upload:function (opt) {
if (opt === 'open') {
this.set('isUploading',true);
- };
+ }
if (opt === 'close') {
this.set('isUploading',false);
- };
+ }
},
sort:function (pr) {
var currentProperty = this.get('sortProperties');
@@ -107,7 +106,7 @@ App.FilesController = Ember.ArrayController.extend({
} else{
this.set('sortProperties',[pr]);
this.set('sortAscending',true);
- };
+ }
},
clearSearchField:function () {
this.set('searchString','');
@@ -168,6 +167,15 @@ App.FilesController = Ember.ArrayController.extend({
}
},
+ clearSearch:function () {
+ this.set('searchString','');
+ }.observes('path'),
+
+ deleteErrorCallback:function (record,error) {
+ this.model.pushRecord(record);
+ this.send('showAlert',error);
+ },
+
throwAlert:function (error) {
this.send('showAlert',error);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/app/models/file.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/models/file.js b/contrib/views/files/src/main/resources/ui/app/models/file.js
index 6908f44..2a8c83c 100644
--- a/contrib/views/files/src/main/resources/ui/app/models/file.js
+++ b/contrib/views/files/src/main/resources/ui/app/models/file.js
@@ -18,7 +18,7 @@
var App = require('app');
-var a = DS.attr;
+var dsa = DS.attr;
App.File = DS.Model.extend({
path: function() {
@@ -28,15 +28,18 @@ App.File = DS.Model.extend({
var path = this.get('id');
return path.substring(0,path.lastIndexOf('/'))||'/';
}.property('id'),
- isDirectory: a('boolean'),
- len: a('number'),
- owner: a('string'),
- group: a('string'),
- permission: a('string'),
- accessTime: a('isodate'),
- modificationTime: a('isodate'),
- blockSize: a('number'),
- replication: a('number'),
+ isDirectory: dsa('boolean'),
+ readAccess: dsa('boolean'),
+ writeAccess: dsa('boolean'),
+ executeAccess: dsa('boolean'),
+ len: dsa('number'),
+ owner: dsa('string'),
+ group: dsa('string'),
+ permission: dsa('string'),
+ accessTime: dsa('isodate'),
+ modificationTime: dsa('isodate'),
+ blockSize: dsa('number'),
+ replication: dsa('number'),
name:function () {
var splitpath = this.get('path').split('/');
return splitpath.get(splitpath.length-1);
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/app/templates/components/contextMenu.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/templates/components/contextMenu.hbs b/contrib/views/files/src/main/resources/ui/app/templates/components/contextMenu.hbs
index 844363c..aa86ed1 100644
--- a/contrib/views/files/src/main/resources/ui/app/templates/components/contextMenu.hbs
+++ b/contrib/views/files/src/main/resources/ui/app/templates/components/contextMenu.hbs
@@ -20,9 +20,9 @@
<div id="context-menu">
<ul class="dropdown-menu dropdown-context compressed-context" role="menu">
{{#if view.target.content.isDirectory}}
- <li><a tabindex="-1" href="#" {{action 'open'}}>Open folder</a></li>
+ <li {{bind-attr class="view.target.content.readAccess::disabled"}}><a tabindex="-1" href="#" {{action 'open'}}>Open folder</a></li>
{{else}}
- <li><a tabindex="-1" href="#" {{action 'download'}}>Download</a></li>
+ <li {{bind-attr class="view.target.content.readAccess::disabled"}}><a tabindex="-1" href="#" {{action 'download'}}>Download</a></li>
{{/if}}
<li><a tabindex="-1" href="#" {{action 'moveFile' 'cut' view.target.content}}>Move</a></li>
<li><a tabindex="-1" href="#" {{action 'showChmod'}} >Permissions</a></li>
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/app/templates/files.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/templates/files.hbs b/contrib/views/files/src/main/resources/ui/app/templates/files.hbs
index 6f65e91..76c439d 100644
--- a/contrib/views/files/src/main/resources/ui/app/templates/files.hbs
+++ b/contrib/views/files/src/main/resources/ui/app/templates/files.hbs
@@ -43,8 +43,8 @@
<div class="panel-body">
<h4 class="i-am-in pull-left"> <i class="fa fa-folder fa-lg"></i>
{{#rename-input file=path confirm='renameDir' isRenaming=isRenaming class='renameable stocked half'}}
- <a href="#" class="dir-name" {{action refreshDir}}>{{currentDir}}</a>
- <a href="#" {{bind-attr class="isRootDir:hide"}} {{action showRenameInput}}><i class="fa fa-edit"></i></a>
+ <a href="#" class="dir-name" {{action 'refreshDir'}}>{{currentDir}}</a>
+ <a href="#" {{bind-attr class="isRootDir:hide"}} {{action 'showRenameInput'}}><i class="fa fa-edit"></i></a>
{{/rename-input}}
</h4>
@@ -68,7 +68,7 @@
<th class="perm" {{action 'sort' 'permission'}} >Permission {{sort-arrow sPs=sortProperties sA=sortAscending sP='permission'}}</th>
<th class="download">
<div class="btn-group btn-sort pull-right" data-toggle="tooltip" data-placement="left" title="Sort by:">
- <button type="button" class="btn btn-xs btn-default" {{action sort 'toggle'}}>
+ <button type="button" class="btn btn-xs btn-default" {{action 'sort' 'toggle'}}>
{{#if sortAscending}} Asc {{else}} Desc {{/if}}
</button>
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/app/templates/util/fileRow.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/templates/util/fileRow.hbs b/contrib/views/files/src/main/resources/ui/app/templates/util/fileRow.hbs
index 052a14e..50693b0 100644
--- a/contrib/views/files/src/main/resources/ui/app/templates/util/fileRow.hbs
+++ b/contrib/views/files/src/main/resources/ui/app/templates/util/fileRow.hbs
@@ -55,10 +55,12 @@
{{#unless isMoving}}
<ul class="list-inline file-actions text-right">
<li>
- {{#if content.isDirectory}}
- <a href="#" {{action 'download' 'zip'}} data-toggle="tooltip" data-placement="bottom" title="Download zip"><i class="fa fa-archive fa-fw fa-lg"></i></a>
- {{else}}
- <a href="#" {{action 'download' 'browse'}} data-toggle="tooltip" data-placement="bottom" title="Download"><i class="fa fa-download fa-fw fa-lg"></i></a>
+ {{#if content.readAccess}}
+ {{#if content.isDirectory}}
+ <a href="#" {{action 'download' 'zip'}} data-toggle="tooltip" data-placement="bottom" title="Download zip"><i class="fa fa-archive fa-fw fa-lg"></i></a>
+ {{else}}
+ <a href="#" {{action 'download' 'browse'}} data-toggle="tooltip" data-placement="bottom" title="Download"><i class="fa fa-download fa-fw fa-lg"></i></a>
+ {{/if}}
{{/if}}
</li>
<li>
@@ -81,4 +83,4 @@
</td>
</tr>
{{chmod-input chVisible=chmodVisible file=content confirm="chmod"}}
-
\ No newline at end of file
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/bower.json
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/bower.json b/contrib/views/files/src/main/resources/ui/bower.json
index 9579a32..b7cb52a 100644
--- a/contrib/views/files/src/main/resources/ui/bower.json
+++ b/contrib/views/files/src/main/resources/ui/bower.json
@@ -5,7 +5,7 @@
"dependencies": {
"ember": "1.7.0",
"ember-data": "1.0.0-beta.9",
- "jquery": "1.9.0",
+ "jquery": "2.x",
"bootstrap": "3.1.x",
"ember-uploader": "~0.2.7",
"ladda-bootstrap": "git://github.com/msurguy/ladda-bootstrap.git#~0.1.0",
@@ -15,9 +15,6 @@
"font-awesome": "~4.0.3"
},
"overrides": {
- "jquery": {
- "main": "jquery.js"
- },
"ember-uploader": {
"main": "dist/ember-uploader.js"
},
@@ -30,8 +27,5 @@
"font-awesome": {
"main": "css/font-awesome.css"
}
- },
- "resolutions": {
- "jquery": "1.9.0"
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/config.coffee
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/config.coffee b/contrib/views/files/src/main/resources/ui/config.coffee
index 36889ce..b7bc79f 100644
--- a/contrib/views/files/src/main/resources/ui/config.coffee
+++ b/contrib/views/files/src/main/resources/ui/config.coffee
@@ -17,8 +17,12 @@
exports.config =
+ watcher:
+ usePolling: true
+
+ fileListInterval: 512
+
files:
-
javascripts:
defaultExtension: 'js'
joinTo:
@@ -35,17 +39,14 @@ exports.config =
defaultExtension: 'hbs'
joinTo: 'javascripts/app.js' : /^app/
paths:
- jquery: 'bower_components/jquery/jquery.js'
+ jquery: 'bower_components/jquery/dist/jquery.js'
handlebars: 'bower_components/handlebars/handlebars.js'
ember: 'bower_components/ember/ember.js'
modules:
addSourceURLs: true
- paths:
- public: '/usr/lib/ambari-server/web/views-debug/FILES/0.1.0/MyFiles/'
-
overrides:
- production:
+ development:
paths:
- public: 'public'
+ public: '/usr/lib/ambari-server/web/views-debug/FILES/0.1.0/MyFiles/'
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/ui/package.json
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/package.json b/contrib/views/files/src/main/resources/ui/package.json
index 54d6788..8ff13e5 100644
--- a/contrib/views/files/src/main/resources/ui/package.json
+++ b/contrib/views/files/src/main/resources/ui/package.json
@@ -22,9 +22,9 @@
"uglify-js-brunch": "^1.7.7",
"clean-css-brunch": "^1.7.1",
"bower": "^1.2.8",
- "brunch": "^1.7.13",
+ "brunch": "1.7.17",
"scaffolt": "^0.4.3",
- "ember-precompiler-brunch": "^1.5.1",
+ "ember-precompiler-brunch": ">= 1.5.0",
"less-brunch": "^1.7.2"
},
"devDependencies": {},
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/main/resources/view.xml
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/view.xml b/contrib/views/files/src/main/resources/view.xml
index 69586d1..5bd72d5 100644
--- a/contrib/views/files/src/main/resources/view.xml
+++ b/contrib/views/files/src/main/resources/view.xml
@@ -20,16 +20,16 @@
<version>0.1.0</version>
<parameter>
- <name>dataworker.defaultFs</name>
- <description>The FileSystem URI (for example, hdfs://c6401.ambari.apache.org:8020)</description>
+ <name>webhdfs.url</name>
+ <description>WebHDFS FileSystem URI (example: webhdfs://namenode:50070)</description>
<required>true</required>
</parameter>
<parameter>
- <name>dataworker.username</name>
- <description>The username (defaults to ViewContext username)</description>
+ <name>webhdfs.username</name>
+ <description>User and doAs for proxy user for HDFS</description>
<required>false</required>
</parameter>
-
+
<resource>
<name>files</name>
<service-class>org.apache.ambari.view.filebrowser.FileBrowserService</service-class>
http://git-wip-us.apache.org/repos/asf/ambari/blob/a6127158/contrib/views/files/src/test/java/org/apache/ambari/view/filebrowser/FilebrowserTest.java
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/test/java/org/apache/ambari/view/filebrowser/FilebrowserTest.java b/contrib/views/files/src/test/java/org/apache/ambari/view/filebrowser/FilebrowserTest.java
index 6eb10e3..b8dcb92 100644
--- a/contrib/views/files/src/test/java/org/apache/ambari/view/filebrowser/FilebrowserTest.java
+++ b/contrib/views/files/src/test/java/org/apache/ambari/view/filebrowser/FilebrowserTest.java
@@ -84,7 +84,7 @@ public class FilebrowserTest{
MiniDFSCluster.Builder builder = new MiniDFSCluster.Builder(conf);
hdfsCluster = builder.build();
String hdfsURI = hdfsCluster.getURI() + "/";
- properties.put("dataworker.defaultFs", hdfsURI);
+ properties.put("webhdfs.url", hdfsURI);
expect(context.getProperties()).andReturn(properties).anyTimes();
expect(context.getUsername()).andReturn(System.getProperty("user.name")).anyTimes();
replay(handler, context, httpHeaders, uriInfo);
@@ -158,7 +158,7 @@ public class FilebrowserTest{
@Test
public void testUsername() throws Exception {
Assert.assertEquals(System.getProperty("user.name"), fileBrowserService.upload().getUsername(context));
- properties.put("dataworker.username", "test-user");
+ properties.put("webhdfs.username", "test-user");
Assert.assertEquals("test-user", fileBrowserService.upload().getUsername(context));
}
[2/2] ambari git commit: AMBARI-8428. "Service actions" drop down
menu is continuously re-created. Added UT (alexantonenko)
Posted by al...@apache.org.
AMBARI-8428. "Service actions" drop down menu is continuously re-created. Added UT (alexantonenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9218a8eb
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9218a8eb
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9218a8eb
Branch: refs/heads/trunk
Commit: 9218a8ebf7011df6f4259c43aa88f14f11673851
Parents: a612715
Author: Alex Antonenko <hi...@gmail.com>
Authored: Wed Nov 26 18:05:14 2014 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Wed Nov 26 18:40:09 2014 +0200
----------------------------------------------------------------------
ambari-web/test/views/main/service/item_test.js | 50 +++++++++++---------
1 file changed, 27 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/9218a8eb/ambari-web/test/views/main/service/item_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/item_test.js b/ambari-web/test/views/main/service/item_test.js
index b35aa6c..c4e847c 100644
--- a/ambari-web/test/views/main/service/item_test.js
+++ b/ambari-web/test/views/main/service/item_test.js
@@ -19,10 +19,13 @@
var App = require('app');
require('views/main/service/item');
+var view;
+
describe('App.MainServiceItemView', function () {
describe('#mastersExcludedCommands', function () {
- var view = App.MainServiceItemView.create({
+
+ view = App.MainServiceItemView.create({
controller: Em.Object.create({
content: Em.Object.create({
hostComponents: []
@@ -61,7 +64,7 @@ describe('App.MainServiceItemView', function () {
});
});
- describe.skip('#observeMaintenance', function () {
+ describe('#observeMaintenance', function () {
var mastersExcludedCommands = {
NAMENODE: ["DECOMMISSION", "REBALANCEHDFS"],
@@ -323,8 +326,14 @@ describe('App.MainServiceItemView', function () {
beforeEach(function () {
+ view = App.MainServiceItemView.create({});
+
sinon.stub(App, 'get', function (k) {
switch (k) {
+ case 'supports.autoRollbackHA':
+ case 'isRMHaEnabled':
+ case 'isHaEnabled':
+ return false;
case 'components.rollinRestartAllowed':
return ["DATANODE", "JOURNALNODE", "ZKFC", "NODEMANAGER", "GANGLIA_MONITOR", "HBASE_REGIONSERVER", "SUPERVISOR", "FLUME_HANDLER"];
case 'components.reassignable':
@@ -375,20 +384,22 @@ describe('App.MainServiceItemView', function () {
testCases.forEach(function (testCase) {
- var view = App.MainServiceItemView.create({
- controller: Em.Object.create({
- content: Em.Object.create({})
- })
- });
-
it('Maintenance for ' + testCase.serviceName + ' service', function () {
- view.set('controller.content', Em.Object.create({
- hostComponents: testCase.hostComponents,
- serviceName: testCase.serviceName,
- displayName: testCase.displayName,
- serviceTypes: testCase.serviceTypes,
- passiveState: 'OFF'
- }));
+ view.reopen({
+ controller: Em.Object.create({
+ content: Em.Object.create({
+ hostComponents: testCase.hostComponents,
+ serviceName: testCase.serviceName,
+ displayName: testCase.displayName,
+ serviceTypes: testCase.serviceTypes,
+ passiveState: 'OFF'
+ }),
+ isSeveralClients: false,
+ clientComponents: []
+ }),
+ mastersExcludedCommands: mastersExcludedCommands,
+ hasConfigTab: hasConfigTab
+ });
if (testCase.controller) {
testCase.controller.forEach(function (item) {
Object.keys(item).forEach(function (key) {
@@ -396,16 +407,9 @@ describe('App.MainServiceItemView', function () {
});
});
}
- view.set('controller.isSeveralClients', false);
- view.set('controller.clientComponents', []);
- view.set('mastersExcludedCommands', mastersExcludedCommands);
- view.set('hasConfigTab', hasConfigTab);
view.observeMaintenanceOnce();
expect(view.get('maintenance')).to.eql(testCase.result);
- });
-
- it('Change isPassive option in maintenance for ' + testCase.serviceName + ' service', function () {
- var oldMaintenance = JSON.parse(JSON.stringify(view.maintenance));
+ var oldMaintenance = JSON.parse(JSON.stringify(view.get('maintenance')));
view.set('controller.content.passiveState', 'ON');
view.observeMaintenanceOnce();
expect(view.get('maintenance')).to.not.eql(oldMaintenance);