diff --git a/hadoop-ozone/docs/content/Settings.md b/hadoop-ozone/docs/content/Settings.md index b2d30e53f1..41ab04a887 100644 --- a/hadoop-ozone/docs/content/Settings.md +++ b/hadoop-ozone/docs/content/Settings.md @@ -53,7 +53,7 @@ following command. This will generate a template called ```ozone-site.xml``` at the specified path (directory). {{< highlight bash >}} -ozone genconf -output +ozone genconf {{< /highlight >}} Let us look at the settings inside the generated file (ozone-site.xml) and diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genconf/GenerateOzoneRequiredConfigurations.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genconf/GenerateOzoneRequiredConfigurations.java index 688b735849..b58cfc2678 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genconf/GenerateOzoneRequiredConfigurations.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genconf/GenerateOzoneRequiredConfigurations.java @@ -18,7 +18,12 @@ package org.apache.hadoop.ozone.genconf; +import org.apache.hadoop.hdds.cli.GenericCli; +import org.apache.hadoop.hdds.cli.HddsVersionProvider; import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; +import picocli.CommandLine.PicocliException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -30,112 +35,58 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; - /** * GenerateOzoneRequiredConfigurations - A tool to generate ozone-site.xml
* This tool generates an ozone-site.xml with minimally required configs. * This tool can be invoked as follows:
* */ -public final class GenerateOzoneRequiredConfigurations { +@Command( + name = "ozone genconf", + description = "Tool to generate template ozone-site.xml", + versionProvider = HddsVersionProvider.class, + mixinStandardHelpOptions = true) +public final class GenerateOzoneRequiredConfigurations extends GenericCli { - private static final String OUTPUT = "-output"; - private static final String HELP = "-help"; - private static final String USAGE = "Usage: \nozone genconf " - + OUTPUT + " \n" - + "ozone genconf " - + HELP; - private static final int SUCCESS = 0; - private static final int FAILURE = 1; + @Parameters(arity = "1..1", + description = "Directory path where ozone-site file should be generated.") + private String path; - private GenerateOzoneRequiredConfigurations() { - - } /** * Entry point for using genconf tool. * * @param args - * @throws JAXBException + * */ - public static void main(String[] args) { - - try { - if (args.length == 0) { - System.out.println(USAGE); - System.exit(1); - } - - switch (args[0]) { - case OUTPUT: - if (args.length > 1) { - int result = generateConfigurations(args[1]); - } else { - System.out.println("Path to output file is mandatory"); - System.out.println(USAGE); - System.exit(1); - } - break; - - case HELP: - System.out.println(USAGE); - System.exit(0); - break; - - default: - System.out.println(USAGE); - System.exit(1); - } - - } catch (Exception e) { - e.printStackTrace(); - } + public static void main(String[] args) throws Exception { + new GenerateOzoneRequiredConfigurations().run(args); } - /** - * Check if the path is valid directory. - * - * @param path - * @return true, if path is valid directory, else return false - */ - public static boolean isValidPath(String path) { - try { - return Files.isDirectory(Paths.get(path)); - } catch (InvalidPathException | NullPointerException ex) { - return false; - } - } - - /** - * Check if user has permission to write in the specified path. - * - * @param path - * @return true, if the user has permission to write, else returns false - */ - public static boolean canWrite(String path) { - File file = new File(path); - return file.canWrite(); + @Override + public Void call() throws Exception { + generateConfigurations(path); + return null; } /** * Generate ozone-site.xml at specified path. - * * @param path - * @return SUCCESS(0) if file can be generated, else returns FAILURE(1) + * @throws PicocliException * @throws JAXBException */ - public static int generateConfigurations(String path) throws JAXBException { + public static void generateConfigurations(String path) throws + PicocliException, JAXBException { if (!isValidPath(path)) { - System.out.println("Invalid directory path."); - return FAILURE; + throw new PicocliException("Invalid directory path."); } if (!canWrite(path)) { - System.out.println("Insufficient permission."); - return FAILURE; + throw new PicocliException("Insufficient permission."); } OzoneConfiguration oc = new OzoneConfiguration(); @@ -168,7 +119,30 @@ public static int generateConfigurations(String path) throws JAXBException { m.marshal(requiredConfig, new File(path, "ozone-site.xml")); System.out.println("ozone-site.xml has been generated at " + path); + } - return SUCCESS; + /** + * Check if the path is valid directory. + * + * @param path + * @return true, if path is valid directory, else return false + */ + public static boolean isValidPath(String path) { + try { + return Files.isDirectory(Paths.get(path)); + } catch (InvalidPathException | NullPointerException ex) { + return Boolean.FALSE; + } + } + + /** + * Check if user has permission to write in the specified path. + * + * @param path + * @return true, if the user has permission to write, else returns false + */ + public static boolean canWrite(String path) { + File file = new File(path); + return file.canWrite(); } } diff --git a/hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/genconf/TestGenerateOzoneRequiredConfigurations.java b/hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/genconf/TestGenerateOzoneRequiredConfigurations.java index 8c75ebb1cb..0fab18514c 100644 --- a/hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/genconf/TestGenerateOzoneRequiredConfigurations.java +++ b/hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/genconf/TestGenerateOzoneRequiredConfigurations.java @@ -21,23 +21,40 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.hadoop.test.GenericTestUtils; -import org.hamcrest.CoreMatchers; +import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import picocli.CommandLine; +import picocli.CommandLine.ExecutionException; +import picocli.CommandLine.IExceptionHandler2; +import picocli.CommandLine.ParseResult; +import picocli.CommandLine.ParameterException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintStream; - +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * Tests GenerateOzoneRequiredConfigurations. */ public class TestGenerateOzoneRequiredConfigurations { private static File outputBaseDir; + private static GenerateOzoneRequiredConfigurations genconfTool; + private static final Logger LOG = + LoggerFactory.getLogger(TestGenerateOzoneRequiredConfigurations.class); + private final ByteArrayOutputStream out = new ByteArrayOutputStream(); + private final ByteArrayOutputStream err = new ByteArrayOutputStream(); + private static final PrintStream OLD_OUT = System.out; + private static final PrintStream OLD_ERR = System.err; /** * Creates output directory which will be used by the test-cases. * If a test-case needs a separate directory, it has to create a random @@ -49,6 +66,24 @@ public class TestGenerateOzoneRequiredConfigurations { public static void init() throws Exception { outputBaseDir = GenericTestUtils.getTestDir(); FileUtils.forceMkdir(outputBaseDir); + genconfTool = new GenerateOzoneRequiredConfigurations(); + } + + @Before + public void setup() throws Exception { + System.setOut(new PrintStream(out)); + System.setErr(new PrintStream(err)); + } + + @After + public void reset() { + // reset stream after each unit test + out.reset(); + err.reset(); + + // restore system streams + System.setOut(OLD_OUT); + System.setErr(OLD_ERR); } /** @@ -59,6 +94,57 @@ public static void cleanup() throws IOException { FileUtils.deleteDirectory(outputBaseDir); } + private void execute(String[] args, String msg) { + List arguments = new ArrayList(Arrays.asList(args)); + LOG.info("Executing shell command with args {}", arguments); + CommandLine cmd = genconfTool.getCmd(); + + IExceptionHandler2> exceptionHandler = + new IExceptionHandler2>() { + @Override + public List handleParseException(ParameterException ex, + String[] args) { + throw ex; + } + + @Override + public List handleExecutionException(ExecutionException ex, + ParseResult parseResult) { + throw ex; + } + }; + cmd.parseWithHandlers(new CommandLine.RunLast(), + exceptionHandler, args); + Assert.assertTrue(out.toString().contains(msg)); + } + + private void executeWithException(String[] args, String msg) { + List arguments = new ArrayList(Arrays.asList(args)); + LOG.info("Executing shell command with args {}", arguments); + CommandLine cmd = genconfTool.getCmd(); + + IExceptionHandler2> exceptionHandler = + new IExceptionHandler2>() { + @Override + public List handleParseException(ParameterException ex, + String[] args) { + throw ex; + } + + @Override + public List handleExecutionException(ExecutionException ex, + ParseResult parseResult) { + throw ex; + } + }; + try{ + cmd.parseWithHandlers(new CommandLine.RunLast(), + exceptionHandler, args); + }catch(Exception ex){ + Assert.assertTrue(ex.getMessage().contains(msg)); + } + } + /** * Tests a valid path and generates ozone-site.xml by calling * {@code GenerateOzoneRequiredConfigurations#generateConfigurations}. @@ -68,79 +154,54 @@ public static void cleanup() throws IOException { @Test public void testGenerateConfigurations() throws Exception { File tempPath = getRandomTempDir(); - String[] args = new String[]{"-output", tempPath.getAbsolutePath()}; - - Assert.assertEquals("Path is valid", - true, GenerateOzoneRequiredConfigurations.isValidPath(args[1])); - - Assert.assertEquals("Permission is valid", - true, GenerateOzoneRequiredConfigurations.canWrite(args[1])); - - Assert.assertEquals("Config file generated", - 0, GenerateOzoneRequiredConfigurations.generateConfigurations(args[1])); + String[] args = new String[]{tempPath.getAbsolutePath()}; + execute(args, "ozone-site.xml has been generated at " + + tempPath.getAbsolutePath()); } /** - * Tests ozone-site.xml generation by calling - * {@code GenerateOzoneRequiredConfigurations#main}. - * + * Test to avoid generating ozone-site.xml when insufficient permission. * @throws Exception */ @Test - public void testGenerateConfigurationsThroughMainMethod() throws Exception { - File tempPath = getRandomTempDir(); - String[] args = new String[]{"-output", tempPath.getAbsolutePath()}; - ByteArrayOutputStream outContent = new ByteArrayOutputStream(); - PrintStream oldStream = System.out; - try (PrintStream ps = new PrintStream(outContent)) { - System.setOut(ps); - GenerateOzoneRequiredConfigurations.main(args); - Assert.assertThat(outContent.toString(), CoreMatchers.containsString( - "ozone-site.xml has been generated at")); - System.setOut(oldStream); - } - } - - /** - * Test to avoid generating ozone-site.xml when invalid permission. - * @throws Exception - */ - @Test - public void generateConfigurationsFailure() throws Exception { + public void genconfFailureByInsufficientPermissions() throws Exception { File tempPath = getRandomTempDir(); tempPath.setReadOnly(); - String[] args = new String[]{"-output", tempPath.getAbsolutePath()}; - GenerateOzoneRequiredConfigurations.main(args); - - Assert.assertEquals("Path is valid", - true, GenerateOzoneRequiredConfigurations.isValidPath(args[1])); - - Assert.assertEquals("Invalid permission", - false, GenerateOzoneRequiredConfigurations.canWrite(args[1])); - - Assert.assertEquals("Config file not generated", - 1, GenerateOzoneRequiredConfigurations.generateConfigurations(args[1])); - tempPath.setWritable(true); + String[] args = new String[]{tempPath.getAbsolutePath()}; + executeWithException(args, "Insufficient permission."); } /** - * Test to avoid generating ozone-site.xml when invalid permission. + * Test to avoid generating ozone-site.xml when invalid path. * @throws Exception */ @Test - public void generateConfigurationsFailureForInvalidPath() throws Exception { + public void genconfFailureByInvalidPath() throws Exception { File tempPath = getRandomTempDir(); - tempPath.setReadOnly(); - String[] args = new String[]{"-output", - tempPath.getAbsolutePath() + "/ozone-site.xml"}; - GenerateOzoneRequiredConfigurations.main(args); + String[] args = new String[]{"invalid-path"}; + executeWithException(args, "Invalid directory path."); + } - Assert.assertEquals("Path is invalid", false, - GenerateOzoneRequiredConfigurations.isValidPath(args[1])); + /** + * Test to avoid generating ozone-site.xml when path not specified. + * @throws Exception + */ + @Test + public void genconfPathNotSpecified() throws Exception { + File tempPath = getRandomTempDir(); + String[] args = new String[]{}; + executeWithException(args, "Missing required parameter: "); + } - Assert.assertEquals("Config file not generated", 1, - GenerateOzoneRequiredConfigurations.generateConfigurations(args[1])); - tempPath.setWritable(true); + /** + * Test to check help message. + * @throws Exception + */ + @Test + public void genconfHelp() throws Exception { + File tempPath = getRandomTempDir(); + String[] args = new String[]{"--help"}; + execute(args, "Usage: ozone genconf [-hV] [--verbose]"); } private File getRandomTempDir() throws IOException {