This is an automated email from the ASF dual-hosted git repository. cshannon pushed a commit to branch 2.1 in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/2.1 by this push: new 87031e9ac7 Support writing cluster config parser output to a file (#3205) 87031e9ac7 is described below commit 87031e9ac7c1cca75aeda285a2df152fabc75ed8 Author: Christopher L. Shannon <christopher.l.shan...@gmail.com> AuthorDate: Wed Mar 1 18:20:12 2023 -0500 Support writing cluster config parser output to a file (#3205) * This commit adds support to provide an optional argument to ClusterConfigParser to write the output to a file instead of System.out so that only the output we want is captured and not everything that's written to standard out. * The accumulo-cluster script has also been updated to to provide the temp file as an output file argument instead of capturing System.out so that there are not parsing errors by the script if other output is written to the standard out stream. --- assemble/bin/accumulo-cluster | 2 +- .../core/conf/cluster/ClusterConfigParser.java | 18 +++++- .../core/conf/cluster/ClusterConfigParserTest.java | 68 +++++++++++++++------- 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/assemble/bin/accumulo-cluster b/assemble/bin/accumulo-cluster index 5bf904b091..3e511dfea2 100755 --- a/assemble/bin/accumulo-cluster +++ b/assemble/bin/accumulo-cluster @@ -66,7 +66,7 @@ function parse_config { trap 'rm -f "$CONFIG_FILE"' EXIT CONFIG_FILE=$(mktemp) || exit 1 - ${accumulo_cmd} org.apache.accumulo.core.conf.cluster.ClusterConfigParser "${conf}"/cluster.yaml >"$CONFIG_FILE" || parse_fail + ${accumulo_cmd} org.apache.accumulo.core.conf.cluster.ClusterConfigParser "${conf}"/cluster.yaml "$CONFIG_FILE" || parse_fail #shellcheck source=/dev/null . "$CONFIG_FILE" rm -f "$CONFIG_FILE" diff --git a/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java b/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java index ec75fd0e06..de43584de0 100644 --- a/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java +++ b/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java @@ -20,6 +20,7 @@ package org.apache.accumulo.core.conf.cluster; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.Paths; @@ -135,12 +136,23 @@ public class ClusterConfigParser { out.flush(); } + @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", + justification = "Path provided for output file is intentional") public static void main(String[] args) throws IOException { - if (args == null || args.length != 1) { - System.err.println("Usage: ClusterConfigParser <configFile>"); + if (args == null || args.length < 1 || args.length > 2) { + System.err.println("Usage: ClusterConfigParser <configFile> [<outputFile>]"); System.exit(1); } - outputShellVariables(parseConfiguration(args[0]), System.out); + + if (args.length == 2) { + // Write to a file instead of System.out if provided as an argument + try (OutputStream os = Files.newOutputStream(Paths.get(args[1]), StandardOpenOption.CREATE); + PrintStream out = new PrintStream(os)) { + outputShellVariables(parseConfiguration(args[0]), new PrintStream(out)); + } + } else { + outputShellVariables(parseConfiguration(args[0]), System.out); + } } } diff --git a/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java b/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java index 8ea7e5a49f..82ca8a41d0 100644 --- a/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java +++ b/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java @@ -26,20 +26,26 @@ import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedReader; import java.io.File; +import java.io.IOException; import java.io.PrintStream; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "paths provided by test") public class ClusterConfigParserTest { + @TempDir + private static File tempDir; + @Test public void testParse() throws Exception { URL configFile = ClusterConfigParserTest.class @@ -109,31 +115,51 @@ public class ClusterConfigParserTest { @Test public void testShellOutput() throws Exception { - String userDir = System.getProperty("user.dir"); - String targetDir = "target"; - File dir = new File(userDir, targetDir); - if (!dir.exists()) { - if (!dir.mkdirs()) { - fail("Unable to make directory ${user.dir}/target"); + testShellOutput(configFile -> { + try { + final Map<String,String> contents = + ClusterConfigParser.parseConfiguration(new File(configFile.toURI()).getAbsolutePath()); + + final File outputFile = new File(tempDir, "ClusterConfigParserTest_testShellOutput"); + if (!outputFile.createNewFile()) { + fail("Unable to create file in " + tempDir); + } + outputFile.deleteOnExit(); + + final PrintStream ps = new PrintStream(outputFile); + ClusterConfigParser.outputShellVariables(contents, ps); + ps.close(); + + return outputFile; + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); } - } - File f = new File(dir, "ClusterConfigParserTest_testShellOutput"); - if (!f.createNewFile()) { - fail("Unable to create file in ${user.dir}/target"); - } - f.deleteOnExit(); + }); + } - PrintStream ps = new PrintStream(f); + @Test + public void testShellOutputMain() throws Exception { + + // Test that the main method in ClusterConfigParser properly parses the configuration + // and outputs to a given file instead of System.out when provided + testShellOutput(configFile -> { + try { + File outputFile = new File(tempDir, "ClusterConfigParserTest_testShellOutputMain"); + ClusterConfigParser.main(new String[] {configFile.getFile(), outputFile.getAbsolutePath()}); + + return outputFile; + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + }); + } - URL configFile = ClusterConfigParserTest.class + private void testShellOutput(Function<URL,File> outputConfigFunction) throws Exception { + final URL configFile = ClusterConfigParserTest.class .getResource("/org/apache/accumulo/core/conf/cluster/cluster.yaml"); assertNotNull(configFile); - Map<String,String> contents = - ClusterConfigParser.parseConfiguration(new File(configFile.toURI()).getAbsolutePath()); - - ClusterConfigParser.outputShellVariables(contents, ps); - ps.close(); + final File f = outputConfigFunction.apply(configFile); Map<String,String> expected = new HashMap<>(); expected.put("MANAGER_HOSTS", "localhost1 localhost2"); @@ -143,9 +169,7 @@ public class ClusterConfigParserTest { expected.put("NUM_TSERVERS", "${NUM_TSERVERS:=1}"); expected.put("NUM_SSERVERS", "${NUM_SSERVERS:=1}"); - expected.replaceAll((k, v) -> { - return '"' + v + '"'; - }); + expected.replaceAll((k, v) -> '"' + v + '"'); Map<String,String> actual = new HashMap<>(); try (BufferedReader rdr = Files.newBufferedReader(Paths.get(f.toURI()))) {