diff --git a/src/main/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPlugin.java b/src/main/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPlugin.java index 5959fb3..32318e1 100644 --- a/src/main/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPlugin.java +++ b/src/main/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPlugin.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,6 +33,8 @@ import com.dtolabs.rundeck.plugins.step.NodeStepPlugin; import com.dtolabs.rundeck.plugins.step.PluginStepContext; +import static com.dtolabs.rundeck.core.Constants.DEBUG_LEVEL; + /** * Workflow Step Plug-in to find value of first matching text file. * @@ -61,55 +62,62 @@ public class ScanFileNodeStepPlugin implements NodeStepPlugin { @PluginProperty(title = "Group", description = "Variable group (i.e., ${group.x}}", required = true, defaultValue = "data") private String group; - @PluginProperty(title = "Name", description = "Variable name (i.e., ${group.name}) [ignored when Pattern has 2 capture fields]", required = false) + @PluginProperty(title = "Name", description = "Variable name (i.e., ${group.name}) [ignored when Pattern has 2 capture fields]") private String name; @PluginProperty(title = "Pattern", description = "Regular expression to find, with one or two capture fields", required = true) private String regex; - @PluginProperty(title = "Make global?", description = "Elevate this variable to global scope (default: false)", required = false) + @PluginProperty(title = "Make global?", description = "Elevate this variable to global scope (default: false)", required = true, defaultValue = "false") private boolean elevateToGlobal; @Override public void executeNodeStep(PluginStepContext context, Map configuration, INodeEntry node) throws NodeStepException { - String path = configuration.getOrDefault("path", this.path).toString(); - String group = configuration.getOrDefault("group", this.group).toString(); - String name = configuration.getOrDefault("name", this.name).toString(); - String regex = configuration.getOrDefault("regex", this.regex).toString(); - boolean elevateToGlobal = configuration.getOrDefault("elevateToGlobal", this.elevateToGlobal).toString() - .equals("true"); - - Pattern pattern = Pattern.compile(regex); - MatchResult match; - Matcher matcher; - String line; + path = configuration.getOrDefault("path", this.path).toString(); + group = configuration.getOrDefault("group", this.group).toString(); + regex = configuration.getOrDefault("regex", this.regex).toString(); + if (configuration.containsKey("elevateToGlobal")) { + elevateToGlobal = configuration.get("elevateToGlobal").toString().equals("true"); + } - if (name == null || name.equals("")) { - name = "data"; + // Setting name is different because it is not a required field. + if (name == null || name.length() == 0) { + name = configuration.getOrDefault("name", "").toString(); + if (name == null || name.length() == 0) { + name = "data"; + } } + Pattern pattern = Pattern.compile(regex); + Map map = new HashMap<>(); - try (BufferedReader reader = new BufferedReader(new FileReader(path))) { + try { + BufferedReader reader = new BufferedReader(new FileReader(path)); // Scan lines for a match. // Optimize by returning immediately when there is only one capture field. - while ((line = reader.readLine()) != null) { - matcher = pattern.matcher(line); - if (matcher.find()) { - match = matcher.toMatchResult(); + do { + String line = reader.readLine(); + if (line == null) { + return; + } + Matcher match = pattern.matcher(line); + if (match.find()) { + context.getLogger().log(DEBUG_LEVEL, "Matched " + line); if (match.groupCount() == 1) { FileLookupUtils.addOutput(context, group, name, match.group(1), elevateToGlobal); return; } else if (match.groupCount() == 2) { + context.getLogger().log(DEBUG_LEVEL, "Found '" + match.group(1) + "' : '" + match.group(2) + "'"); // Take first value and do not overwrite, even though scanning proceeds // through the rest of the file to find other matches to the pattern. - if (map.get(match.group(1)) == null) { + if (!map.containsKey(match.group(1))) { FileLookupUtils.addOutput(context, group, match.group(1), match.group(2), elevateToGlobal); map.put(match.group(1), match.group(2)); } } } - } + } while (true); } catch (FileNotFoundException e) { String msg = "Could not find file " + path; String nodeName = node.getNodename(); diff --git a/src/main/java/com/bioraft/rundeck/filelookup/ScanFileStepPlugin.java b/src/main/java/com/bioraft/rundeck/filelookup/ScanFileStepPlugin.java index 5f04f75..a289d0a 100644 --- a/src/main/java/com/bioraft/rundeck/filelookup/ScanFileStepPlugin.java +++ b/src/main/java/com/bioraft/rundeck/filelookup/ScanFileStepPlugin.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -33,6 +32,8 @@ import com.dtolabs.rundeck.plugins.step.PluginStepContext; import com.dtolabs.rundeck.plugins.step.StepPlugin; +import static com.dtolabs.rundeck.core.Constants.DEBUG_LEVEL; + /** * Workflow Step Plug-in to find value of first matching text file. * @@ -60,51 +61,61 @@ public class ScanFileStepPlugin implements StepPlugin { @PluginProperty(title = "Group", description = "Variable group (i.e., ${group.x}}", required = true, defaultValue = "data") private String group; - @PluginProperty(title = "Name", description = "Variable name (i.e., ${group.name}) [ignored when Pattern has 2 capture fields]", required = false) + @PluginProperty(title = "Name", description = "Variable name (i.e., ${group.name}) [ignored when Pattern has 2 capture fields]") private String name; @PluginProperty(title = "Pattern", description = "Regular expression to find, with one or two capture fields", required = true) private String regex; - @PluginProperty(title = "Make global?", description = "Elevate this variable to global scope (default: false)", required = false) + @PluginProperty(title = "Make global?", description = "Elevate this variable to global scope (default: false)", required = true, defaultValue = "false") private boolean elevateToGlobal; @Override public void executeStep(PluginStepContext context, Map configuration) throws StepException { - String path = configuration.getOrDefault("path", this.path).toString(); - String group = configuration.getOrDefault("group", this.group).toString(); - String name = configuration.getOrDefault("name", this.name).toString(); - String regex = configuration.getOrDefault("regex", this.regex).toString(); - boolean elevateToGlobal = configuration.getOrDefault("elevateToGlobal", this.elevateToGlobal).toString() - .equals("true"); - - Pattern pattern = Pattern.compile(regex); - MatchResult match; - Matcher matcher; - String line; + path = configuration.getOrDefault("path", this.path).toString(); + group = configuration.getOrDefault("group", this.group).toString(); + regex = configuration.getOrDefault("regex", this.regex).toString(); + if (configuration.containsKey("elevateToGlobal")) { + elevateToGlobal = configuration.get("elevateToGlobal").toString().equals("true"); + } - if (name == null || name.equals("")) { - name = "data"; + // Setting name is different because it is not a required field. + if (name == null || name.length() == 0) { + name = configuration.getOrDefault("name", "").toString(); + if (name == null || name.length() == 0) { + name = "data"; + } } + Pattern pattern = Pattern.compile(regex); + Map map = new HashMap<>(); - try (BufferedReader reader = new BufferedReader(new FileReader(path))) { + try { + BufferedReader reader = new BufferedReader(new FileReader(path)); // Scan lines for a match. // Optimize by returning immediately when there is only one capture field. - while ((line = reader.readLine()) != null) { - matcher = pattern.matcher(line); - if (matcher.find()) { - match = matcher.toMatchResult(); + do { + String line = reader.readLine(); + if (line == null) { + return; + } + Matcher match = pattern.matcher(line); + if (match.find()) { + context.getLogger().log(DEBUG_LEVEL, "Matched " + line); if (match.groupCount() == 1) { FileLookupUtils.addOutput(context, group, name, match.group(1), elevateToGlobal); return; } else if (match.groupCount() == 2) { - if (map.get(match.group(1)) == null) { + context.getLogger().log(DEBUG_LEVEL, "Found '" + match.group(1) + "' : '" + match.group(2) + "'"); + // Take first value and do not overwrite, even though scanning proceeds + // through the rest of the file to find other matches to the pattern. + if (!map.containsKey(match.group(1))) { + FileLookupUtils.addOutput(context, group, match.group(1), match.group(2), elevateToGlobal); map.put(match.group(1), match.group(2)); } } } - } + } while (true); } catch (FileNotFoundException e) { String msg = "Could not find file " + path; throw new StepException(msg, e, FileLookupFailureReason.FileNotFound); @@ -112,8 +123,5 @@ public void executeStep(PluginStepContext context, Map configura String msg = "Could not read file " + path; throw new StepException(msg, e, FileLookupFailureReason.FileNotReadable); } - for (Map.Entry element : map.entrySet()) { - FileLookupUtils.addOutput(context, group, element.getKey(), element.getValue(), elevateToGlobal); - } } } diff --git a/src/test/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPluginTest.java b/src/test/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPluginTest.java index 4b35054..cd563b2 100644 --- a/src/test/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPluginTest.java +++ b/src/test/java/com/bioraft/rundeck/filelookup/ScanFileNodeStepPluginTest.java @@ -29,6 +29,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.dtolabs.rundeck.plugins.PluginLogger; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,6 +63,9 @@ public class ScanFileNodeStepPluginTest { @Mock SharedOutputContext sharedOutputContext; + @Mock + PluginLogger logger; + @Captor ArgumentCaptor nameCaptor; @@ -76,6 +80,8 @@ public void setUp() { configuration = Stream.of(new String[][] { { "path", "testData/test.yaml" }, { "group", "example" }, { "name", "key" }, { "regex", "single" }, }) .collect(Collectors.toMap(data -> data[0], data -> data[1])); + when(context.getLogger()).thenReturn(logger); + } @Test(expected = StepException.class) diff --git a/src/test/java/com/bioraft/rundeck/filelookup/ScanFileStepPluginTest.java b/src/test/java/com/bioraft/rundeck/filelookup/ScanFileStepPluginTest.java index f9580d9..4b75b42 100644 --- a/src/test/java/com/bioraft/rundeck/filelookup/ScanFileStepPluginTest.java +++ b/src/test/java/com/bioraft/rundeck/filelookup/ScanFileStepPluginTest.java @@ -16,8 +16,7 @@ package com.bioraft.rundeck.filelookup; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.matches; +import static org.mockito.Matchers.*; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -29,6 +28,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.dtolabs.rundeck.plugins.PluginLogger; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -58,6 +58,9 @@ public class ScanFileStepPluginTest { @Mock SharedOutputContext sharedOutputContext; + @Mock + PluginLogger logger; + @Captor ArgumentCaptor nameCaptor; @@ -72,6 +75,7 @@ public void setUp() { configuration = Stream.of(new String[][] { { "path", "testData/test.yaml" }, { "group", "example" }, { "name", "key" }, { "regex", "single" }, }) .collect(Collectors.toMap(data -> data[0], data -> data[1])); + when(context.getLogger()).thenReturn(logger); } @Test(expected = StepException.class) @@ -83,7 +87,7 @@ public void noFileThrowsException() throws StepException { @Test public void canRunWithoutMatch() throws StepException { - configuration.put("regex", "com[.]example[.]label3: (.*)"); + configuration.put("regex", "^\\s+com[.]example[.]label3: (.*)"); when(context.getOutputContext()).thenReturn(sharedOutputContext); this.plugin.executeStep(context, configuration); @@ -110,7 +114,7 @@ public void canFindSingleCapture() throws StepException { @Test public void canFindMultipleCapture() throws StepException { - configuration.put("regex", "com[.]example[.](label1|label2): (.*)"); + configuration.put("regex", "^\\s+com[.]example[.](label1|label2): (.*)"); when(context.getOutputContext()).thenReturn(sharedOutputContext); this.plugin.executeStep(context, configuration);