Skip to content

Commit

Permalink
+ editCommands
Browse files Browse the repository at this point in the history
  • Loading branch information
Vitasek committed Nov 28, 2017
1 parent 211818a commit b67b965
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 2 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,13 @@ Pre-defined launch scripts are located in the zip file. You can modify it locall
For our purposes we also integrated following commands:
- ```set showResultCodeON``` and ```set showResultCodeOFF``` - if it's enabled, it will write command result code after its completion
- ```cd```, ```pwd```
- ```edit 'my file'``` - see the config below


###### Edit Command
Since the version 1.0.4 the simple command 'edit' is available. The command gets selected file from HDFS to the local temporary directory and launchs editor. Once the editor saves the file (with a result code 0), the file is uploaded back into HDFS (target file is overwritten).
By default the editor path is taken from ```$EDITOR``` environment variable. If ```$EDITOR``` is not set, ```vim``` (Linux, Mac) or ```notepad.exe``` (Windows) is used.

### Running Daemon mode
![Image of HDFS-Shell](https://github.com/avast/hdfs-shell/blob/master/web/screenshot2.png)

Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ dependencies {
compile 'com.kohlschutter.junixsocket:junixsocket-native-common:2.0.4'
compile 'com.kohlschutter.junixsocket:junixsocket-common:2.0.4'

compile "org.apache.commons:commons-lang3:3.3.2"
compile "org.apache.hadoop:hadoop-client:2.6.0"

testCompile 'junit:junit:4.12'
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
springShellVersion = 1.2.0.RELEASE
theGroup=com.avast.server
theVersion=1.0.3
theVersion=1.0.4
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public synchronized Configuration getConfiguration() {
return configuration;
}

private FileSystem getFileSystem() throws IOException {
FileSystem getFileSystem() throws IOException {
final Configuration conf = getConfiguration();
return FileSystem.get(conf);
}
Expand Down
133 changes: 133 additions & 0 deletions src/main/java/com/avast/server/hdfsshell/commands/EditCommands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.avast.server.hdfsshell.commands;

import com.avast.server.hdfsshell.utils.BashUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.UUID;
import java.util.stream.Collectors;

/**
* @author Vitasek L.
*/
@Component
public class EditCommands implements CommandMarker {

private static final Logger logger = LoggerFactory.getLogger(EditCommands.class);

final HadoopDfsCommands hadoopDfsCommands;
private final ContextCommands contextCommands;


@Value("${EDITOR:}")
String editor;

@Autowired
public EditCommands(HadoopDfsCommands hadoopDfsCommands, ContextCommands contextCommands) {
this.hadoopDfsCommands = hadoopDfsCommands;
this.contextCommands = contextCommands;
}


@SuppressWarnings("ResultOfMethodCallIgnored")
@CliCommand(value = "edit", help = "Get file to local file system, edit and put it back to HDFS")
public String set(@CliOption(key = {"_raw_"}, help = "File to edit") String path) throws IOException {
if (StringUtils.isEmpty(path)) {
return "You have to define path param";
}
Path p = getFilePathForEdit(path);

if (!contextCommands.getFileSystem().exists(p)) {
return "Path " + p + " does not exists. Invalid file?";
}

final File localTempFile = getLocalTempFile(p.getName());
try {
final String getCommandResult = hadoopDfsCommands.runCommand("get", new String[]{p.toString(), localTempFile.getAbsolutePath()});
if (StringUtils.isEmpty(getCommandResult)) {
if (editFile(localTempFile)) {
final String putCommandResult = hadoopDfsCommands.runCommand("put", new String[]{"-f", localTempFile.getAbsolutePath(), p.toString()});
if (StringUtils.isEmpty(putCommandResult)) {
logger.info("File {} was updated successfully", p.getName());
return "File " + p.getName() + " was updated succesfully.";
}
} else {
return "File " + p.getName() + " was NOT updated.";
}
}

} catch (Exception e) {
return "Failed to edit file: " + e.getMessage();
} finally {
localTempFile.delete();
}


return "";
}

private Path getFilePathForEdit(@CliOption(key = {"_raw_"}, help = "File to edit") String path) {
Path p;
if (!path.startsWith("/")) {
p = new Path(contextCommands.getCurrentDir(), path);
} else {
p = new Path(path);
}
return p;
}

private File getLocalTempFile(String filename) {
return new File(FileUtils.getTempDirectory(), UUID.randomUUID().toString().substring(0, 10) + "-" + filename);
}


public boolean editFile(final File file) throws IOException, InterruptedException {
final long lastModified = file.lastModified();
final String[] editor = getEditor();
if (editor.length == 0) {
System.out.println("No editor is defined");
return false;
}

final ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(editor, file.getAbsolutePath()));
// Merge System.err and System.out
pb.redirectErrorStream(true);
// Inherit System.out as redirect output stream
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
logger.info("Launching command {}", pb.command().stream().collect(Collectors.joining(" ")));

final Process process = pb.start();
final int resultCode = process.waitFor();
return resultCode == 0 && lastModified != file.lastModified();
}

public String[] getEditor() {
if (StringUtils.isEmpty(this.editor)) {
if (SystemUtils.IS_OS_WINDOWS) {
return new String[]{"notepad.exe"};
}
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_MAC_OSX) {
return new String[]{"vim"};
}
return new String[]{"vim"};
} else {
return BashUtils.parseArguments(this.editor);
}
}

}

0 comments on commit b67b965

Please sign in to comment.