AMBARI-15829. Files View: Extract the directory viewer UI component so that other views can use it. (dipayanb)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/281307fc Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/281307fc Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/281307fc Branch: refs/heads/trunk Commit: 281307fceb533c1a557d9972991263546288bb41 Parents: 33ef653 Author: Dipayan Bhowmick <[email protected]> Authored: Wed Apr 13 17:52:01 2016 +0530 Committer: Dipayan Bhowmick <[email protected]> Committed: Wed Apr 13 17:52:01 2016 +0530 ---------------------------------------------------------------------- contrib/views/commons/README.md | 84 ++++ contrib/views/commons/pom.xml | 140 ++++++ .../MisconfigurationFormattedException.java | 43 ++ .../exceptions/NotFoundFormattedException.java | 27 ++ .../exceptions/ServiceFormattedException.java | 57 +++ .../view/commons/hdfs/FileOperationService.java | 479 ++++++++++++++++++ .../ambari/view/commons/hdfs/HdfsService.java | 160 ++++++ .../ambari/view/commons/hdfs/UploadService.java | 138 ++++++ .../ambari/view/commons/hdfs/UserService.java | 106 ++++ .../resources/ui/hdfs-directory-viewer/.bowerrc | 4 + .../ui/hdfs-directory-viewer/.editorconfig | 34 ++ .../ui/hdfs-directory-viewer/.ember-cli | 27 ++ .../ui/hdfs-directory-viewer/.gitignore | 17 + .../ui/hdfs-directory-viewer/.jshintrc | 32 ++ .../ui/hdfs-directory-viewer/.npmignore | 30 ++ .../ui/hdfs-directory-viewer/.travis.yml | 50 ++ .../ui/hdfs-directory-viewer/.watchmanconfig | 21 + .../ui/hdfs-directory-viewer/LICENSE.md | 28 ++ .../ui/hdfs-directory-viewer/README.md | 97 ++++ .../ui/hdfs-directory-viewer/addon/.gitkeep | 0 .../addon/components/directory-viewer.js | 196 ++++++++ .../templates/components/directory-viewer.hbs | 18 + .../addon/utils/viewer-config.js | 59 +++ .../ui/hdfs-directory-viewer/app/.gitkeep | 0 .../app/components/directory-viewer.js | 19 + .../app/utils/viewer-config.js | 19 + .../ui/hdfs-directory-viewer/bower.json | 19 + .../hdfs-directory-viewer/config/ember-try.js | 54 +++ .../hdfs-directory-viewer/config/environment.js | 24 + .../ui/hdfs-directory-viewer/ember-cli-build.js | 36 ++ .../resources/ui/hdfs-directory-viewer/index.js | 32 ++ .../ui/hdfs-directory-viewer/package.json | 51 ++ .../ui/hdfs-directory-viewer/testem.json | 12 + .../ui/hdfs-directory-viewer/tests/.jshintrc | 52 ++ .../tests/dummy/app/app.js | 36 ++ .../tests/dummy/app/components/.gitkeep | 0 .../tests/dummy/app/controllers/.gitkeep | 0 .../tests/dummy/app/controllers/application.js | 32 ++ .../tests/dummy/app/helpers/.gitkeep | 0 .../tests/dummy/app/index.html | 43 ++ .../tests/dummy/app/models/.gitkeep | 0 .../tests/dummy/app/router.js | 29 ++ .../tests/dummy/app/routes/.gitkeep | 0 .../tests/dummy/app/styles/app.css | 23 + .../tests/dummy/app/templates/application.hbs | 36 ++ .../dummy/app/templates/components/.gitkeep | 0 .../tests/dummy/app/utils/my-viewer-config.js | 35 ++ .../tests/dummy/config/environment.js | 65 +++ .../tests/dummy/public/crossdomain.xml | 15 + .../tests/dummy/public/robots.txt | 3 + .../tests/helpers/destroy-app.js | 23 + .../tests/helpers/module-for-acceptance.js | 41 ++ .../tests/helpers/resolver.js | 29 ++ .../tests/helpers/start-app.js | 36 ++ .../ui/hdfs-directory-viewer/tests/index.html | 52 ++ .../tests/integration/.gitkeep | 0 .../hdfs-directory-viewer/tests/test-helper.js | 24 + .../hdfs-directory-viewer/tests/unit/.gitkeep | 0 .../ui/hdfs-directory-viewer/vendor/.gitkeep | 0 contrib/views/files/pom.xml | 5 + .../view/filebrowser/DownloadService.java | 8 +- .../view/filebrowser/FileBrowserService.java | 13 +- .../view/filebrowser/FileOperationService.java | 484 ------------------- .../view/filebrowser/FilePreviewService.java | 7 +- .../ambari/view/filebrowser/HdfsService.java | 160 ------ .../ambari/view/filebrowser/HelpService.java | 67 +-- .../ambari/view/filebrowser/UploadService.java | 137 ------ .../MisconfigurationFormattedException.java | 43 -- .../utils/NotFoundFormattedException.java | 27 -- .../utils/ServiceFormattedException.java | 57 --- .../resources/ui/app/services/file-operation.js | 4 +- .../files/src/main/resources/ui/package.json | 5 + .../view/filebrowser/FilebrowserTest.java | 1 + contrib/views/pom.xml | 1 + 74 files changed, 2721 insertions(+), 985 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/README.md ---------------------------------------------------------------------- diff --git a/contrib/views/commons/README.md b/contrib/views/commons/README.md new file mode 100644 index 0000000..b956fbd --- /dev/null +++ b/contrib/views/commons/README.md @@ -0,0 +1,84 @@ +<!--- +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](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. +--> + +#Ambari Views Commons Module + +Have this as a dependency in the view which need the functionality. + +This has common code for: + +* HDFS access + +**Note: More to be added later** + +### How to Include it in dependant project + +In the service class for the project use `commons` projects code in the way described in the below example for `files` view. + +```java +package org.apache.ambari.view.filebrowser; + +import javax.ws.rs.Path; + +import org.apache.ambari.view.ViewContext; + +import com.google.inject.Inject; +import org.apache.ambari.view.commons.hdfs.FileOperationService; +import org.apache.ambari.view.commons.hdfs.UploadService; +import org.apache.ambari.view.commons.hdfs.UserService; + +/** + * Root files service + */ +public class FileBrowserService { + + @Inject + ViewContext context; + + /** + * @see UploadService + * @return service + */ + @Path("/upload") + public UploadService upload() { + return new UploadService(context); + } + + /** + * @see org.apache.ambari.view.commons.hdfs.FileOperationService + * @return service + */ + @Path("/fileops") + public FileOperationService fileOps() { + return new FileOperationService(context); + } + + /** + * @see org.apache.ambari.view.commons.hdfs.UserService + * @return service + */ + @Path("/user") + public UserService userService() { return new UserService(context); } + +} +``` + + +####Also, look into the various ember addons that are included in `src/main/resources/ui`. +Currently we have: + +* hdfs-directory-viewer + +**More to be added later** \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/pom.xml ---------------------------------------------------------------------- diff --git a/contrib/views/commons/pom.xml b/contrib/views/commons/pom.xml new file mode 100644 index 0000000..5018d46 --- /dev/null +++ b/contrib/views/commons/pom.xml @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <artifactId>ambari-views-commons</artifactId> + <version>2.0.0.0-SNAPSHOT</version> + <name>Ambari View Commons</name> + + <parent> + <artifactId>ambari-contrib-views</artifactId> + <groupId>org.apache.ambari.contrib.views</groupId> + <version>2.0.0.0-SNAPSHOT</version> + </parent> + + <dependencies> + <dependency> + <groupId>org.apache.ambari.contrib.views</groupId> + <artifactId>ambari-views-utils</artifactId> + <version>2.0.0.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.ambari</groupId> + <artifactId>ambari-views</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-hdfs</artifactId> + <version>${hadoop.version}</version> + <exclusions> + <exclusion> + <groupId>tomcat</groupId> + <artifactId>jasper-runtime</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-common</artifactId> + <version>${hadoop.version}</version> + <exclusions> + <exclusion> + <groupId>tomcat</groupId> + <artifactId>jasper-runtime</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>com.google.inject</groupId> + <artifactId>guice</artifactId> + </dependency> + + <dependency> + <groupId>com.googlecode.json-simple</groupId> + <artifactId>json-simple</artifactId> + </dependency> + + <dependency> + <groupId>com.sun.jersey.contribs</groupId> + <artifactId>jersey-multipart</artifactId> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.4</version> + </dependency> + + <!-- Testing --> + <dependency> + <groupId>com.sun.jersey.jersey-test-framework</groupId> + <artifactId>jersey-test-framework-core</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-minicluster</artifactId> + <version>${hadoop.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.easymock</groupId> + <artifactId>easymock</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <directory>src/main/resources/</directory> + <filtering>false</filtering> + <excludes> + <exclude>ui/**</exclude> + </excludes> + </resource> + </resources> + </build> + + <properties> + <ambari.dir>${project.parent.parent.parent.basedir}</ambari.dir> + </properties> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/MisconfigurationFormattedException.java ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/MisconfigurationFormattedException.java b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/MisconfigurationFormattedException.java new file mode 100644 index 0000000..b7ce938 --- /dev/null +++ b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/MisconfigurationFormattedException.java @@ -0,0 +1,43 @@ +/** + * 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. + */ + +package org.apache.ambari.view.commons.exceptions; + +import org.json.simple.JSONObject; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.HashMap; + +public class MisconfigurationFormattedException extends WebApplicationException { + private final static int STATUS = 500; + private final static String message = "Parameter \"%s\" is set to null"; + + public MisconfigurationFormattedException(String name) { + super(errorEntity(name)); + } + + protected static Response errorEntity(String name) { + HashMap<String, Object> response = new HashMap<String, Object>(); + response.put("message", String.format(message, name)); + response.put("trace", null); + response.put("status", STATUS); + return Response.status(STATUS).entity(new JSONObject(response)).type(MediaType.APPLICATION_JSON).build(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/NotFoundFormattedException.java ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/NotFoundFormattedException.java b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/NotFoundFormattedException.java new file mode 100644 index 0000000..a8c51f7 --- /dev/null +++ b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/NotFoundFormattedException.java @@ -0,0 +1,27 @@ +/** + * 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. + */ + +package org.apache.ambari.view.commons.exceptions; + +public class NotFoundFormattedException extends ServiceFormattedException { + private final static int STATUS = 404; + + public NotFoundFormattedException(String message, Throwable exception) { + super(message, exception, STATUS); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/ServiceFormattedException.java ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/ServiceFormattedException.java b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/ServiceFormattedException.java new file mode 100644 index 0000000..bb77404 --- /dev/null +++ b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/exceptions/ServiceFormattedException.java @@ -0,0 +1,57 @@ +/** + * 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. + */ + +package org.apache.ambari.view.commons.exceptions; + +import org.apache.commons.lang.exception.ExceptionUtils; +import org.json.simple.JSONObject; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.security.AccessControlException; +import java.util.HashMap; + +public class ServiceFormattedException extends WebApplicationException { + public ServiceFormattedException(String message, Throwable exception) { + super(errorEntity(message, exception, suggestStatus(exception))); + } + + public ServiceFormattedException(String message, Throwable exception, int status) { + super(errorEntity(message, exception, status)); + } + + private static int suggestStatus(Throwable exception) { + int status = 500; + if (exception instanceof AccessControlException) { + status = 403; + } + return status; + } + + protected static Response errorEntity(String message, Throwable e, int status) { + HashMap<String, Object> response = new HashMap<String, Object>(); + response.put("message", message); + String trace = null; + if (e != null) + trace = ExceptionUtils.getStackTrace(e); + response.put("trace", trace); + response.put("status", status); + return Response.status(status).entity(new JSONObject(response)).type(MediaType.APPLICATION_JSON).build(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/FileOperationService.java ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/FileOperationService.java b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/FileOperationService.java new file mode 100644 index 0000000..bc3d11d --- /dev/null +++ b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/FileOperationService.java @@ -0,0 +1,479 @@ +/** + * 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. + */ + +package org.apache.ambari.view.commons.hdfs; + +import org.apache.ambari.view.ViewContext; +import org.apache.ambari.view.commons.exceptions.NotFoundFormattedException; +import org.apache.ambari.view.commons.exceptions.ServiceFormattedException; +import org.apache.ambari.view.utils.hdfs.HdfsApi; +import org.apache.ambari.view.utils.hdfs.HdfsApiException; +import org.json.simple.JSONObject; + +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +/** + * File operations service + */ +public class FileOperationService extends HdfsService { + + /** + * Constructor + * @param context View Context instance + */ + public FileOperationService(ViewContext context) { + super(context); + } + + /** + * List dir + * @param path path + * @return response with dir content + */ + @GET + @Path("/listdir") + @Produces(MediaType.APPLICATION_JSON) + public Response listdir(@QueryParam("path") String path) { + try { + JSONObject response = new JSONObject(); + response.put("files", getApi(context).fileStatusToJSON(getApi(context).listdir(path))); + response.put("meta", getApi(context).fileStatusToJSON(getApi(context).getFileStatus(path))); + return Response.ok(response).build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (FileNotFoundException ex) { + throw new NotFoundFormattedException(ex.getMessage(), ex); + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Rename + * @param request rename request + * @return response with success + */ + @POST + @Path("/rename") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response rename(final SrcDstFileRequest request) { + try { + HdfsApi api = getApi(context); + ResponseBuilder result; + if (api.rename(request.src, request.dst)) { + result = Response.ok(getApi(context).fileStatusToJSON(api + .getFileStatus(request.dst))); + } else { + result = Response.ok(new FileOperationResult(false, "Can't move '" + request.src + "' to '" + request.dst + "'")).status(422); + } + return result.build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Chmod + * @param request chmod request + * @return response with success + */ + @POST + @Path("/chmod") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response chmod(final ChmodRequest request) { + try { + HdfsApi api = getApi(context); + ResponseBuilder result; + if (api.chmod(request.path, request.mode)) { + result = Response.ok(getApi(context).fileStatusToJSON(api + .getFileStatus(request.path))); + } else { + result = Response.ok(new FileOperationResult(false, "Can't chmod '" + request.path + "'")).status(422); + } + return result.build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Copy file + * @param request source and destination request + * @return response with success + */ + @POST + @Path("/move") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response move(final MultiSrcDstFileRequest request, + @Context HttpHeaders headers, @Context UriInfo ui) { + try { + HdfsApi api = getApi(context); + ResponseBuilder result; + String message = ""; + + List<String> sources = request.sourcePaths; + String destination = request.destinationPath; + if(sources.isEmpty()) { + result = Response.ok(new FileOperationResult(false, "Can't move 0 file/folder to '" + destination + "'")). + status(422); + return result.build(); + } + + int index = 0; + for (String src : sources) { + String fileName = getFileName(src); + String finalDestination = getDestination(destination, fileName); + try { + if (api.rename(src, finalDestination)) { + index ++; + } else { + message = "Failed to move '" + src + "' to '" + finalDestination + "'"; + break; + } + } catch (IOException exception) { + message = exception.getMessage(); + logger.error("Failed to move '{}' to '{}'. Exception: {}", src, finalDestination, + exception.getMessage()); + break; + } + } + if (index == sources.size()) { + result = Response.ok(new FileOperationResult(true)).status(200); + } else { + FileOperationResult errorResult = getFailureFileOperationResult(sources, index, message); + result = Response.ok(errorResult).status(422); + } + return result.build(); + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Copy file + * @param request source and destination request + * @return response with success + */ + @POST + @Path("/copy") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response copy(final MultiSrcDstFileRequest request, + @Context HttpHeaders headers, @Context UriInfo ui) { + try { + HdfsApi api = getApi(context); + ResponseBuilder result; + String message = ""; + + List<String> sources = request.sourcePaths; + String destination = request.destinationPath; + if(sources.isEmpty()) { + result = Response.ok(new FileOperationResult(false, "Can't copy 0 file/folder to '" + destination + "'")). + status(422); + return result.build(); + } + + int index = 0; + for (String src : sources) { + String fileName = getFileName(src); + String finalDestination = getDestination(destination, fileName); + try { + api.copy(src, finalDestination); + index ++; + } catch (IOException|HdfsApiException exception) { + message = exception.getMessage(); + logger.error("Failed to copy '{}' to '{}'. Exception: {}", src, finalDestination, + exception.getMessage()); + break; + } + } + if (index == sources.size()) { + result = Response.ok(new FileOperationResult(true)).status(200); + } else { + FileOperationResult errorResult = getFailureFileOperationResult(sources, index, message); + result = Response.ok(errorResult).status(422); + } + return result.build(); + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Make directory + * @param request make directory request + * @return response with success + */ + @PUT + @Path("/mkdir") + @Produces(MediaType.APPLICATION_JSON) + public Response mkdir(final MkdirRequest request) { + try{ + HdfsApi api = getApi(context); + ResponseBuilder result; + if (api.mkdir(request.path)) { + result = Response.ok(getApi(context).fileStatusToJSON(api.getFileStatus(request.path))); + } else { + result = Response.ok(new FileOperationResult(false, "Can't create dir '" + request.path + "'")).status(422); + } + return result.build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Empty trash + * @return response with success + */ + @DELETE + @Path("/trash/emptyTrash") + @Produces(MediaType.APPLICATION_JSON) + public Response emptyTrash() { + try { + HdfsApi api = getApi(context); + api.emptyTrash(); + return Response.ok(new FileOperationResult(true)).build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Move to trash + * @param request remove request + * @return response with success + */ + @DELETE + @Path("/moveToTrash") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response moveToTrash(MultiRemoveRequest request) { + try { + ResponseBuilder result; + HdfsApi api = getApi(context); + String trash = api.getTrashDirPath(); + String message = ""; + + if (request.paths.size() == 0) { + result = Response.ok(new FileOperationResult(false, "No path entries provided.")).status(422); + } else { + if (!api.exists(trash)) { + if (!api.mkdir(trash)) { + result = Response.ok(new FileOperationResult(false, "Trash dir does not exists. Can't create dir for " + + "trash '" + trash + "'")).status(422); + return result.build(); + } + } + + int index = 0; + for (MultiRemoveRequest.PathEntry entry : request.paths) { + String trashFilePath = api.getTrashDirPath(entry.path); + try { + if (api.rename(entry.path, trashFilePath)) { + index ++; + } else { + message = "Failed to move '" + entry.path + "' to '" + trashFilePath + "'"; + break; + } + } catch (IOException exception) { + message = exception.getMessage(); + logger.error("Failed to move '{}' to '{}'. Exception: {}", entry.path, trashFilePath, + exception.getMessage()); + break; + } + } + if (index == request.paths.size()) { + result = Response.ok(new FileOperationResult(true)).status(200); + } else { + FileOperationResult errorResult = getFailureFileOperationResult(getPathsFromPathsEntries(request.paths), index, message); + result = Response.ok(errorResult).status(422); + } + } + return result.build(); + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Remove + * @param request remove request + * @return response with success + */ + @DELETE + @Path("/remove") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response remove(MultiRemoveRequest request, @Context HttpHeaders headers, + @Context UriInfo ui) { + try { + HdfsApi api = getApi(context); + ResponseBuilder result; + String message = ""; + if(request.paths.size() == 0) { + result = Response.ok(new FileOperationResult(false, "No path entries provided.")); + } else { + int index = 0; + for (MultiRemoveRequest.PathEntry entry : request.paths) { + try { + if (api.delete(entry.path, entry.recursive)) { + index++; + } else { + message = "Failed to remove '" + entry.path + "'"; + break; + } + } catch (IOException exception) { + message = exception.getMessage(); + logger.error("Failed to remove '{}'. Exception: {}", entry.path, exception.getMessage()); + break; + } + + } + if (index == request.paths.size()) { + result = Response.ok(new FileOperationResult(true)).status(200); + } else { + FileOperationResult errorResult = getFailureFileOperationResult(getPathsFromPathsEntries(request.paths), index, message); + result = Response.ok(errorResult).status(422); + } + } + return result.build(); + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + private List<String> getPathsFromPathsEntries(List<MultiRemoveRequest.PathEntry> paths) { + List<String> entries = new ArrayList<>(); + for(MultiRemoveRequest.PathEntry path: paths) { + entries.add(path.path); + } + return entries; + } + + private FileOperationResult getFailureFileOperationResult(List<String> paths, int failedIndex, String message) { + List<String> succeeded = new ArrayList<>(); + List<String> unprocessed = new ArrayList<>(); + List<String> failed = new ArrayList<>(); + ListIterator<String> iter = paths.listIterator(); + while (iter.hasNext()) { + int index = iter.nextIndex(); + String path = iter.next(); + if (index < failedIndex) { + succeeded.add(path); + } else if (index == failedIndex) { + failed.add(path); + } else { + unprocessed.add(path); + } + } + return new FileOperationResult(false, message, succeeded, failed, unprocessed); + } + + private String getDestination(String baseDestination, String fileName) { + if(baseDestination.endsWith("/")) { + return baseDestination + fileName; + } else { + return baseDestination + "/" + fileName; + } + } + + private String getFileName(String srcPath) { + return srcPath.substring(srcPath.lastIndexOf('/') + 1); + } + + + /** + * Wrapper for json mapping of mkdir request + */ + @XmlRootElement + public static class MkdirRequest { + @XmlElement(nillable = false, required = true) + public String path; + } + + /** + * Wrapper for json mapping of chmod request + */ + @XmlRootElement + public static class ChmodRequest { + @XmlElement(nillable = false, required = true) + public String path; + @XmlElement(nillable = false, required = true) + public String mode; + } + + /** + * Wrapper for json mapping of request with + * source and destination + */ + @XmlRootElement + public static class SrcDstFileRequest { + @XmlElement(nillable = false, required = true) + public String src; + @XmlElement(nillable = false, required = true) + public String dst; + } + + /** + * Wrapper for json mapping of request with multiple + * source and destination + */ + @XmlRootElement + public static class MultiSrcDstFileRequest { + @XmlElement(nillable = false, required = true) + public List<String> sourcePaths = new ArrayList<>(); + @XmlElement(nillable = false, required = true) + public String destinationPath; + } + + /** + * Wrapper for json mapping of remove request + */ + @XmlRootElement + public static class MultiRemoveRequest { + @XmlElement(nillable = false, required = true) + public List<PathEntry> paths = new ArrayList<>(); + public static class PathEntry { + @XmlElement(nillable = false, required = true) + public String path; + public boolean recursive; + } + + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/HdfsService.java ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/HdfsService.java b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/HdfsService.java new file mode 100644 index 0000000..91eebcf --- /dev/null +++ b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/HdfsService.java @@ -0,0 +1,160 @@ +/** + * 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. + */ + +package org.apache.ambari.view.commons.hdfs; + +import javax.ws.rs.WebApplicationException; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.ambari.view.ViewContext; +import org.apache.ambari.view.commons.exceptions.ServiceFormattedException; +import org.apache.ambari.view.utils.hdfs.HdfsApi; +import org.apache.ambari.view.utils.hdfs.HdfsUtil; +import org.apache.hadoop.security.UserGroupInformation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Base Hdfs service + */ +public abstract class HdfsService { + + protected static final Logger logger = LoggerFactory.getLogger(HdfsService.class); + + protected final ViewContext context; + + /** + * Constructor + * @param context View Context instance + */ + public HdfsService(ViewContext context) { + this.context = context; + } + + /** + * Wrapper for json mapping of result of Multi Remove Request + */ + @XmlRootElement + public static class FileOperationResult { + public boolean success; + public String message; + public List<String> succeeded; + public List<String> failed; + public List<String> unprocessed; + + public FileOperationResult(boolean success) { + this.success = success; + } + + public FileOperationResult(boolean success, String message) { + this(success); + this.message = message; + } + + public FileOperationResult(boolean success, String message, List<String> succeeded, List<String> failed, List<String> unprocessed) { + this(success, message); + this.succeeded = succeeded; + this.failed = failed; + this.unprocessed = unprocessed; + } + + } + + private HdfsApi _api = null; + + /** + * Ger HdfsApi instance + * @param context View Context instance + * @return HdfsApi business delegate + */ + public HdfsApi getApi(ViewContext context) { + if (_api == null) { + try { + _api = HdfsUtil.connectToHDFSApi(context); + } catch (Exception ex) { + throw new ServiceFormattedException("HdfsApi connection failed. Check \"webhdfs.url\" property", ex); + } + } + return _api; + } + + private static Map<String, String> getHdfsAuthParams(ViewContext context) { + String auth = context.getProperties().get("webhdfs.auth"); + Map<String, String> params = new HashMap<String, String>(); + if (auth == null || auth.isEmpty()) { + auth = "auth=SIMPLE"; + } + for(String param : auth.split(";")) { + String[] keyvalue = param.split("="); + if (keyvalue.length != 2) { + logger.error("Can not parse authentication param " + param + " in " + auth); + continue; + } + params.put(keyvalue[0], keyvalue[1]); + } + return params; + } + + /** + * Get doAs username to use in HDFS + * @param context View Context instance + * @return user name + */ + public String getDoAsUsername(ViewContext context) { + String username = context.getProperties().get("webhdfs.username"); + if (username == null || username.isEmpty()) + username = context.getUsername(); + return username; + } + + /** + * Checks connection to HDFS + * @param context View Context + */ + public static void hdfsSmokeTest(ViewContext context) { + try { + HdfsApi api = HdfsUtil.connectToHDFSApi(context); + api.getStatus(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Get proxyuser username to use in HDFS + * @param context View Context instance + * @return user name + */ + public String getRealUsername(ViewContext context) { + String username = context.getProperties().get("webhdfs.proxyuser"); + if (username == null || username.isEmpty()) + try { + username = UserGroupInformation.getCurrentUser().getShortUserName(); + } catch (IOException e) { + throw new ServiceFormattedException("HdfsApi connection failed. Can't get current user", e); + } + return username; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UploadService.java ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UploadService.java b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UploadService.java new file mode 100644 index 0000000..97253ad --- /dev/null +++ b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UploadService.java @@ -0,0 +1,138 @@ +/** + * 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. + */ + +package org.apache.ambari.view.commons.hdfs; + +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.ambari.view.ViewContext; +import org.apache.ambari.view.commons.exceptions.ServiceFormattedException; +import org.apache.ambari.view.commons.hdfs.HdfsService; +import org.apache.ambari.view.utils.hdfs.HdfsApi; +import org.apache.hadoop.fs.FSDataOutputStream; + +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataParam; + +/** + * Upload service + */ +public class UploadService extends HdfsService { + + /** + * Constructor + * @param context View Context instance + */ + public UploadService(ViewContext context) { + super(context); + } + + private void uploadFile(final String filePath, InputStream uploadedInputStream) + throws IOException, InterruptedException { + int read; + byte[] chunk = new byte[1024]; + FSDataOutputStream out = null; + try { + out = getApi(context).create(filePath, false); + while ((read = uploadedInputStream.read(chunk)) != -1) { + out.write(chunk, 0, read); + } + } finally { + if (out != null) { + out.close(); + } + } + } + + /** + * Upload file + * @param uploadedInputStream file input stream + * @param contentDisposition content disposition + * @param path path + * @return file status + */ + @PUT + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.APPLICATION_JSON) + public Response uploadFile( + @FormDataParam("file") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition contentDisposition, + @FormDataParam("path") String path) { + try { + if (!path.endsWith("/")) + path = path + "/"; + String filePath = path + contentDisposition.getFileName(); + uploadFile(filePath, uploadedInputStream); + return Response.ok( + getApi(context).fileStatusToJSON(getApi(context).getFileStatus(filePath))) + .build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Upload zip and unpack + * @param uploadedInputStream file input stream + * @param contentDisposition content disposition + * @param path path + * @return files statuses + * @throws IOException + * @throws Exception + */ + @PUT + @Path("/zip") + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.APPLICATION_JSON) + public Response uploadZip( + @FormDataParam("file") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition contentDisposition, + @FormDataParam("path") String path) { + try { + if (!path.endsWith("/")) + path = path + "/"; + ZipInputStream zip = new ZipInputStream(uploadedInputStream); + ZipEntry ze = zip.getNextEntry(); + HdfsApi api = getApi(context); + while (ze != null) { + String filePath = path + ze.getName(); + if (ze.isDirectory()) { + api.mkdir(filePath); + } else { + uploadFile(filePath, zip); + } + ze = zip.getNextEntry(); + } + return Response.ok(getApi(context).fileStatusToJSON(api.listdir(path))).build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UserService.java ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UserService.java b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UserService.java new file mode 100644 index 0000000..dc303ce --- /dev/null +++ b/contrib/views/commons/src/main/java/org/apache/ambari/view/commons/hdfs/UserService.java @@ -0,0 +1,106 @@ +/** + * 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. + */ + +package org.apache.ambari.view.commons.hdfs; + +import org.apache.ambari.view.ViewContext; +import org.apache.ambari.view.commons.exceptions.NotFoundFormattedException; +import org.apache.ambari.view.commons.exceptions.ServiceFormattedException; +import org.apache.ambari.view.utils.hdfs.HdfsApi; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.FileNotFoundException; + +/** + * User related info service + */ +public class UserService extends HdfsService { + + /** + * Constructor + * @param context View Context instance + */ + public UserService(ViewContext context) { + super(context); + } + + /** + * Returns home directory + * @return home directory + */ + @GET + @Path("/home") + @Produces(MediaType.APPLICATION_JSON) + public Response homeDir() { + try { + HdfsApi api = getApi(context); + return Response + .ok(getApi(context).fileStatusToJSON(api.getFileStatus(api.getHomeDir() + .toString()))).build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Is trash enabled + * @return is trash enabled + */ + @GET + @Path("/trash/enabled") + @Produces(MediaType.APPLICATION_JSON) + public Response trashEnabled() { + try { + HdfsApi api = getApi(context); + return Response.ok(new FileOperationResult(api.trashEnabled())).build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } + + /** + * Trash dir + * @return trash dir + */ + @GET + @Path("/trashDir") + @Produces(MediaType.APPLICATION_JSON) + public Response trashdir() { + try { + HdfsApi api = getApi(context); + return Response.ok( + getApi(context).fileStatusToJSON(api.getFileStatus(api.getTrashDir() + .toString()))).build(); + } catch (WebApplicationException ex) { + throw ex; + } catch (FileNotFoundException ex) { + throw new NotFoundFormattedException(ex.getMessage(), ex); + } catch (Exception ex) { + throw new ServiceFormattedException(ex.getMessage(), ex); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.bowerrc ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.bowerrc b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.bowerrc new file mode 100644 index 0000000..959e169 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.bowerrc @@ -0,0 +1,4 @@ +{ + "directory": "bower_components", + "analytics": false +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.editorconfig ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.editorconfig b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.editorconfig new file mode 100644 index 0000000..47c5438 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.editorconfig @@ -0,0 +1,34 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.js] +indent_style = space +indent_size = 2 + +[*.hbs] +insert_final_newline = false +indent_style = space +indent_size = 2 + +[*.css] +indent_style = space +indent_size = 2 + +[*.html] +indent_style = space +indent_size = 2 + +[*.{diff,md}] +trim_trailing_whitespace = false http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.ember-cli ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.ember-cli b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.ember-cli new file mode 100644 index 0000000..5a339b9 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.ember-cli @@ -0,0 +1,27 @@ +/** + * 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. + */ + +{ + /** + Ember CLI sends analytics information by default. The data is completely + anonymous, but there are times when you might want to disable this behavior. + + Setting `disableAnalytics` to true will prevent any data from being sent. + */ + "disableAnalytics": false +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.gitignore ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.gitignore b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.gitignore new file mode 100644 index 0000000..86fceae --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.gitignore @@ -0,0 +1,17 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp + +# dependencies +/node_modules +/bower_components + +# misc +/.sass-cache +/connect.lock +/coverage/* +/libpeerconnection.log +npm-debug.log +testem.log http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.jshintrc ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.jshintrc b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.jshintrc new file mode 100644 index 0000000..08096ef --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.jshintrc @@ -0,0 +1,32 @@ +{ + "predef": [ + "document", + "window", + "-Promise" + ], + "browser": true, + "boss": true, + "curly": true, + "debug": false, + "devel": true, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "eqnull": true, + "esnext": true, + "unused": true +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.npmignore ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.npmignore b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.npmignore new file mode 100644 index 0000000..fea9ccc --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.npmignore @@ -0,0 +1,30 @@ +# 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. + +bower_components/ +tests/ +tmp/ +dist/ + +.bowerrc +.editorconfig +.ember-cli +.travis.yml +.npmignore +**/.gitkeep +bower.json +Brocfile.js +testem.json http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.travis.yml ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.travis.yml b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.travis.yml new file mode 100644 index 0000000..dbc0990 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.travis.yml @@ -0,0 +1,50 @@ +# 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. + +--- +language: node_js +node_js: + - "0.12" + +sudo: false + +cache: + directories: + - node_modules + +env: + - EMBER_TRY_SCENARIO=default + - EMBER_TRY_SCENARIO=ember-release + - EMBER_TRY_SCENARIO=ember-beta + - EMBER_TRY_SCENARIO=ember-canary + +matrix: + fast_finish: true + allow_failures: + - env: EMBER_TRY_SCENARIO=ember-canary + +before_install: + - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH + - "npm config set spin false" + - "npm install -g npm@^2" + +install: + - npm install -g bower + - npm install + - bower install + +script: + - ember try $EMBER_TRY_SCENARIO test http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.watchmanconfig ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.watchmanconfig b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.watchmanconfig new file mode 100644 index 0000000..6ec27cc --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/.watchmanconfig @@ -0,0 +1,21 @@ +/** + * 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. + */ + +{ + "ignore_dirs": ["tmp", "dist"] +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/LICENSE.md ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/LICENSE.md b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/LICENSE.md new file mode 100644 index 0000000..c1f9da4 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/LICENSE.md @@ -0,0 +1,28 @@ +<!--- +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](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. +--> + +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](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. + http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/README.md ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/README.md b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/README.md new file mode 100644 index 0000000..d383a93 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/README.md @@ -0,0 +1,97 @@ +<!--- +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](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. +--> + +# Hdfs-directory-viewer + +Ember Addon to view the HDFS file system. + +Different Ambari views can use this in their view. Common code should be usable in every view. + +# How to use it + +### Including it in dependant project +Add the following code in package.json of the dependant view + +```javascript +"name": "files", +"ember-addon": { + "paths": [ + "../../../../../commons/src/main/resources/ui/hdfs-directory-viewer" + ] +} +``` + +`paths` is an array which includes all the addons shares in ```commons``` library. The entries should be the relative path to the addon in this ```commons``` repository. + +### Including the UI dependencies in the dependent project +As we are going to include the component using the `ember-addon` config in `package.json` and not by the `ember install` way, the UI dependencies also has to be included in the dependent projects `bower.json` file if not already added. + +``` +"bootstrap": "~3.3.6", +"bootstrap-treeview": "~1.2.0", +"font-awesome": "~4.5.0" +``` + +### Overriding configs in dependant project + +Create a util object in `utils` directory using `ember generate util <object name>` and override it as follows: + +```javascript +import ViewerConfig from 'hdfs-directory-viewer/utils/viewer-config'; + +export default ViewerConfig.extend({ + showOnlyDirectories: true, + + expandIcon: 'fa fa-chevron-right', + collapseIcon: 'fa fa-chevron-down', + + listDirectoryUrl(pathParams) { + return `/api/v1/views/FILES/versions/1.0.0/instances/files/resources/files/fileops/listdir?${pathParams}`; + } +}); +``` + +All the functions and attributes in `hdfs-directory-viewer/utils/viewer-config` can be overriden + +### Passing the object to the view template + +```javascript +import Ember from 'ember'; +import MyViewerConfig from '../utils/my-viewer-config'; + +export default Ember.Controller.extend({ + config: MyViewerConfig.create(), + actions: { + viewerError: function() { + console.log("Failed to fetch the content!!!"); + }, + viewerSelectedPath: function(data) { + console.log(`User selected: path: ${data.path}, isDirectory: ${data.isDirectory}`); + } + } +}); +``` + +```html +... +<div class="directory-viewer-wrap"> + {{directory-viewer + config=config + errorAction="viewerError" + pathSelectAction="viewerSelectedPath" + }} +</div> +... +``` http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/.gitkeep ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/.gitkeep b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/.gitkeep new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/components/directory-viewer.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/components/directory-viewer.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/components/directory-viewer.js new file mode 100644 index 0000000..991d122 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/components/directory-viewer.js @@ -0,0 +1,196 @@ +/** + * 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. + */ + +import Ember from 'ember'; +import layout from '../templates/components/directory-viewer'; + +export default Ember.Component.extend({ + layout, + config: Ember.Object.create({}), + classNames: ['directory-viewer'], + startPath: '/', + treeData: Ember.A(), + currentPath: Ember.computed.oneWay('startPath'), + currentQueryParam: Ember.computed('currentPath', function() { + return Ember.$.param({path: this.get('currentPath')}); + }), + + startFetch: Ember.on('didInitAttrs', function() { + this.fetchData(); + }), + + + fetchData: function() { + this.listPath(this.get('currentQueryParam')).then( + (response) => { + let list = this.filterDirectoriesIfRequired(response.files); + this.modifyTreeViewData(list); + }, (error) => { + this.sendAction('errorAction', error); + } + ); + }, + + /** + * Makes a XHR call and returns a promise. + */ + listPath: function(params) { + let config = this.get('config'); + let listUrl = config.listDirectoryUrl(params); + let headers = config.getHeaders(); + return Ember.$.ajax(listUrl, { + headers: headers + }); + }, + + filterDirectoriesIfRequired: function(files) { + let showOnlyDirectories = this.get('config.showOnlyDirectories'); + return files.filter((entry) => { + return (!(showOnlyDirectories) || entry.isDirectory); + }); + }, + + modifyTreeViewData: function(response) { + let paths = response.map((entry) => { + let isDirectory = entry.isDirectory; + let icon = isDirectory ? this.get('config.folderIcon') : this.get('config.fileIcon'); + let data = { + path: entry.path, + pathSegment: this.getNameForPath(entry.path), + isDirectory: isDirectory, + icon: icon, + text: this.getNameForPath(entry.path) + }; + if(isDirectory) { + data.nodes = Ember.A(); + } + return data; + }); + + var currentPath = this.get('currentPath'); + var newTreeData = Ember.copy(this.get('treeData'), true); + if(currentPath === '/') { + newTreeData = paths; + } else { + this.insertPathToTreeData(newTreeData, paths, currentPath.substring(1)); + } + + this.set('treeData', newTreeData); + this.send('refreshTreeView'); + }, + + insertPathToTreeData(treeData, paths, pathSegment) { + let firstPathSegment; + if (pathSegment.indexOf('/') !== -1) { + firstPathSegment = pathSegment.substring(0, pathSegment.indexOf('/')); + } else { + firstPathSegment = pathSegment; + } + + if(treeData.length === 0) { + treeData.pushObjects(paths); + } else { + treeData.forEach((entry) => { + entry.state = {}; + if (entry.pathSegment === firstPathSegment) { + entry.state.expanded = true; + if(entry.nodes.length === 0) { + paths.forEach((pathEntry) => { + entry.nodes.push(pathEntry); + }); + } else { + this.insertPathToTreeData(entry.nodes, paths, pathSegment.substring(pathSegment.indexOf('/') + 1)); + } + } else { + this.collapseAll(entry); + } + }); + } + }, + + collapseAll: function(node) { + if (Ember.isNone(node.state)) { + node.state = {}; + } + node.state.expanded = false; + if(!Ember.isNone(node.nodes)) { + node.nodes.forEach((entry) => { + this.collapseAll(entry); + }); + } + }, + + getNameForPath: function(path) { + return path.substring(path.lastIndexOf("/") + 1); + }, + + collapseAllExceptPath: function(pathSegment) { + let collapseAll = function(nodes, pathSegment) { + var firstPathSegment; + if (pathSegment.indexOf('/') !== -1) { + firstPathSegment = pathSegment.substring(0, pathSegment.indexOf('/')); + } else { + firstPathSegment = pathSegment; + } + + nodes.forEach((entry) => { + if (Ember.isNone(entry.state)) { + entry.state = {}; + } + if(firstPathSegment !== entry.pathSegment) { + entry.state.expanded = false; + } else { + entry.state.expanded = true; + collapseAll(entry.nodes, pathSegment.substring(pathSegment.indexOf('/') + 1)); + } + }); + }; + var newTreeData = this.get('treeData'); + collapseAll(newTreeData, pathSegment); + this.set('treeData', newTreeData); + this.send('refreshTreeView'); + }, + + actions: { + refreshTreeView() { + Ember.run.later(() => { + this.$().treeview({ + data: this.get('treeData'), + expandIcon: this.get('config.expandIcon'), + collapseIcon: this.get('config.collapseIcon'), + //emptyIcon: "fa", + showBorder: false, + onNodeSelected: (event, data) => { + this.set('currentPath', data.path); + this.sendAction('pathSelectAction', {path: data.path, isDirectory: data.isDirectory}); + }, + onNodeExpanded: (event, data) => { + this.set('currentPath', data.path); + if (!Ember.isNone(data.nodes) && data.nodes.length === 0) { + var node = this.$().treeview('getNode', data.nodeId); + node.icon = "fa fa-refresh fa-spin"; + this.fetchData(); + } else { + this.collapseAllExceptPath(data.path.substring(1)); + } + } + }); + }); + } + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/templates/components/directory-viewer.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/templates/components/directory-viewer.hbs b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/templates/components/directory-viewer.hbs new file mode 100644 index 0000000..75339c5 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/templates/components/directory-viewer.hbs @@ -0,0 +1,18 @@ +{{! +* 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. +}} + http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/utils/viewer-config.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/utils/viewer-config.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/utils/viewer-config.js new file mode 100644 index 0000000..64773c6 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/addon/utils/viewer-config.js @@ -0,0 +1,59 @@ +/** + * 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. + */ + +import Ember from 'ember'; + +export default Ember.Object.extend({ + + /** + * Set this to true, if only directory listing is required. + */ + showOnlyDirectories: false, + + /** + * Set this to true, if refresh of current path is required. + */ + showRefreshButton: false, + + /** + * Override these for different Icon. Refer https://github.com/jonmiles/bootstrap-treeview + */ + expandIcon: "fa fa-plus", + collapseIcon: "fa fa-minus", + //Custom + fileIcon: "fa fa-file", + folderIcon: "fa fa-folder", + + /** + * Override to return the headers add to the XHR call made for various operations. + * The Overriding object can also merge its result with the default in this object. + */ + getHeaders() { + return {"X-Requested-By": "ambari"}; + }, + + /** + * Return the URL endpoint for XHR call meant for listing Directories + * @param pathParams + * @returns {string} + */ + listDirectoryUrl(pathParams) { + return `/listdir?${pathParams}`; + } + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/.gitkeep ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/.gitkeep b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/.gitkeep new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/components/directory-viewer.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/components/directory-viewer.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/components/directory-viewer.js new file mode 100644 index 0000000..e704ef7 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/components/directory-viewer.js @@ -0,0 +1,19 @@ +/** + * 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. + */ + +export { default } from 'hdfs-directory-viewer/components/directory-viewer'; http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/utils/viewer-config.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/utils/viewer-config.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/utils/viewer-config.js new file mode 100644 index 0000000..f175b6c --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/app/utils/viewer-config.js @@ -0,0 +1,19 @@ +/** + * 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. + */ + +export { default } from 'hdfs-directory-viewer/utils/viewer-config'; http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/bower.json ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/bower.json b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/bower.json new file mode 100644 index 0000000..f016904 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/bower.json @@ -0,0 +1,19 @@ +{ + "name": "hdfs-directory-viewer", + "dependencies": { + "ember": "2.2.0", + "ember-cli-shims": "0.1.0", + "ember-cli-test-loader": "0.2.2", + "ember-load-initializers": "0.1.7", + "ember-qunit-notifications": "0.1.0", + "jquery": "1.11.3", + "loader.js": "^3.5.0", + "qunit": "~1.20.0", + "bootstrap": "~3.3.6", + "bootstrap-treeview": "~1.2.0", + "font-awesome": "~4.5.0" + }, + "resolutions": { + "ember": "2.2.0" + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/ember-try.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/ember-try.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/ember-try.js new file mode 100644 index 0000000..252dff2 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/ember-try.js @@ -0,0 +1,54 @@ +/** + * 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. + */ + +/*jshint node:true*/ +module.exports = { + scenarios: [ + { + name: 'default', + dependencies: { } + }, + { + name: 'ember-release', + dependencies: { + 'ember': 'components/ember#release' + }, + resolutions: { + 'ember': 'release' + } + }, + { + name: 'ember-beta', + dependencies: { + 'ember': 'components/ember#beta' + }, + resolutions: { + 'ember': 'beta' + } + }, + { + name: 'ember-canary', + dependencies: { + 'ember': 'components/ember#canary' + }, + resolutions: { + 'ember': 'canary' + } + } + ] +}; http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/environment.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/environment.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/environment.js new file mode 100644 index 0000000..4a4b263 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/config/environment.js @@ -0,0 +1,24 @@ +/** + * 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. + */ + +/*jshint node:true*/ +'use strict'; + +module.exports = function(/* environment, appConfig */) { + return { }; +}; http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/ember-cli-build.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/ember-cli-build.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/ember-cli-build.js new file mode 100644 index 0000000..f6aac28 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/ember-cli-build.js @@ -0,0 +1,36 @@ +/** + * 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. + */ + +/*jshint node:true*/ +/* global require, module */ +var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); + +module.exports = function(defaults) { + var app = new EmberAddon(defaults, { + // Add options here + }); + + /* + This build file specifies the options for the dummy test app of this + addon, located in `/tests/dummy` + This build file does *not* influence how the addon or the app using it + behave. You most likely want to be modifying `./index.js` or app's build file + */ + + return app.toTree(); +}; http://git-wip-us.apache.org/repos/asf/ambari/blob/281307fc/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/index.js ---------------------------------------------------------------------- diff --git a/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/index.js b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/index.js new file mode 100644 index 0000000..dc074d7 --- /dev/null +++ b/contrib/views/commons/src/main/resources/ui/hdfs-directory-viewer/index.js @@ -0,0 +1,32 @@ +/** + * 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. + */ + +/* jshint node: true */ +'use strict'; + +module.exports = { + name: 'hdfs-directory-viewer', + included: function(app) { + this._super.included(app); + + app.import(app.bowerDirectory + '/bootstrap/dist/css/bootstrap.css'); + app.import(app.bowerDirectory + '/bootstrap/dist/js/bootstrap.js'); + app.import(app.bowerDirectory + '/bootstrap-treeview/src/js/bootstrap-treeview.js'); + app.import(app.bowerDirectory + '/bootstrap-treeview/dist/bootstrap-treeview.min.css'); + } +};
