Skip to content

Commit

Permalink
Merge pull request #4 from kdebisschop/fail-on-invalid-cases-json
Browse files Browse the repository at this point in the history
Fail when JSON for cases is not valid
  • Loading branch information
kdebisschop authored Feb 8, 2020
2 parents 31170cf + e2776c6 commit 03ee493
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 50 deletions.
52 changes: 30 additions & 22 deletions src/main/java/com/bioraft/rundeck/conditional/Switch.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.dtolabs.rundeck.core.Constants;
import com.dtolabs.rundeck.core.dispatcher.ContextView;
import com.dtolabs.rundeck.core.execution.workflow.steps.FailureReason;
import com.dtolabs.rundeck.plugins.step.PluginStepContext;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -57,15 +58,22 @@ public Switch(PluginStepContext ctx) {
* @param elevate If specified, also create a variable in global export
* context.
*/
public void switchCase(String group, String name, String cases, String test, String defaultValue, boolean elevate) {
public void switchCase(String group, String name, String cases, String test, String defaultValue, boolean elevate) throws JsonProcessingException {
// If no case was matched, assign defaultValue if it is not null.
if (!switchCase(group, name, cases, test, elevate)) {
if (defaultValue != null && defaultValue.length() > 0) {
addOutput(elevate, group, name, defaultValue);
ctx.getLogger().log(Constants.DEBUG_LEVEL, "No match, using default.");
} else {
ctx.getLogger().log(Constants.DEBUG_LEVEL, "No match, default is empty.");
try {
if (!switchCase(group, name, cases, test, elevate)) {
if (defaultValue != null && defaultValue.length() > 0) {
addOutput(elevate, group, name, defaultValue);
ctx.getLogger().log(Constants.DEBUG_LEVEL, "No match, using default.");
} else {
ctx.getLogger().log(Constants.DEBUG_LEVEL, "No match, default is empty.");
}
}
} catch (JsonProcessingException e) {
ctx.getLogger().log(Constants.ERR_LEVEL, "Failed to parse cases.");
ctx.getLogger().log(Constants.ERR_LEVEL, e.getMessage());
e.printStackTrace();
throw e;
}
}

Expand All @@ -80,23 +88,19 @@ public void switchCase(String group, String name, String cases, String test, Str
*
* @return True if matched, false otherwise.
*/
public boolean switchCase(String group, String name, String cases, String test, boolean elevate) {
public boolean switchCase(String group, String name, String cases, String test, boolean elevate) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode map = objectMapper.readTree(ensureStringIsJsonObject(cases));
Iterator<Map.Entry<String, JsonNode>> iterator = map.fields();
while (iterator.hasNext()) {
Map.Entry<String, JsonNode> entry = iterator.next();
String key = entry.getKey();
String value = entry.getValue().asText();
if (test.equals(key)) {
addOutput(elevate, group, name, value);
ctx.getLogger().log(Constants.DEBUG_LEVEL, "Matched " + key + ".");
return true;
}
JsonNode map = objectMapper.readTree(ensureStringIsJsonObject(cases));
Iterator<Map.Entry<String, JsonNode>> iterator = map.fields();
while (iterator.hasNext()) {
Map.Entry<String, JsonNode> entry = iterator.next();
String key = entry.getKey();
String value = entry.getValue().asText();
if (test.equals(key)) {
addOutput(elevate, group, name, value);
ctx.getLogger().log(Constants.DEBUG_LEVEL, "Matched " + key + ".");
return true;
}
} catch (JsonProcessingException e) {
return false;
}
return false;
}
Expand Down Expand Up @@ -125,4 +129,8 @@ public static String ensureStringIsJsonObject(String string) {
String trimmed = string.replaceFirst("^\\s*\\{?", "{").replaceFirst("\\s*$", "");
return trimmed + (trimmed.endsWith("}") ? "" : "}");
}

enum Causes implements FailureReason {
InvalidJSON
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.dtolabs.rundeck.plugins.descriptions.RenderingOptions;
import com.dtolabs.rundeck.plugins.step.NodeStepPlugin;
import com.dtolabs.rundeck.plugins.step.PluginStepContext;
import com.fasterxml.jackson.core.JsonProcessingException;

import static com.dtolabs.rundeck.core.plugins.configuration.StringRenderingConstants.CODE_SYNTAX_MODE;
import static com.dtolabs.rundeck.core.plugins.configuration.StringRenderingConstants.DISPLAY_TYPE_KEY;
Expand Down Expand Up @@ -61,21 +62,23 @@ public class SwitchCaseNodeStepPlugin implements NodeStepPlugin {
@PluginProperty(title = "Test Value", description = "Test value", required = true)
private String testValue;

@PluginProperty(title = "Default", description = "Default value", required = false)
@PluginProperty(title = "Default", description = "Default value")
private String defaultValue;

@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)")
private boolean elevateToGlobal;

@Override
public void executeNodeStep(PluginStepContext ctx, Map<String, Object> cfg, INodeEntry node)
throws NodeStepException {

String group = cfg.getOrDefault("group", this.group).toString();
String name = cfg.getOrDefault("name", this.name).toString();
String cases = cfg.getOrDefault("cases", this.cases).toString();
String testValue = cfg.getOrDefault("testValue", this.testValue).toString();
boolean elevateToGlobal = cfg.getOrDefault("elevateToGlobal", this.elevateToGlobal).equals("true");
group = cfg.getOrDefault("group", this.group).toString();
name = cfg.getOrDefault("name", this.name).toString();
cases = cfg.getOrDefault("cases", this.cases).toString();
testValue = cfg.getOrDefault("testValue", this.testValue).toString();
if (cfg.containsKey("elevateToGlobal")) {
elevateToGlobal = cfg.get("elevateToGlobal").equals("true");
}

boolean globalHasDefault = defaultValue != null && defaultValue.length() > 0;
boolean cfgHasDefault = cfg.containsKey("defaultValue") && cfg.get("defaultValue") != null;
Expand All @@ -86,10 +89,14 @@ public void executeNodeStep(PluginStepContext ctx, Map<String, Object> cfg, INod
ctx.getLogger().log(Constants.DEBUG_LEVEL,
"Setting " + group + "." + name + " based on " + testValue + " " + cases);

if (cfgHasDefault || globalHasDefault) {
(new Switch(ctx)).switchCase(group, name, cases, testValue, defaultValue, elevateToGlobal);
} else {
(new Switch(ctx)).switchCase(group, name, cases, testValue, elevateToGlobal);
try {
if (cfgHasDefault || globalHasDefault) {
(new Switch(ctx)).switchCase(group, name, cases, testValue, defaultValue, elevateToGlobal);
} else {
(new Switch(ctx)).switchCase(group, name, cases, testValue, elevateToGlobal);
}
} catch (JsonProcessingException e) {
throw new NodeStepException(e.getMessage(), Switch.Causes.InvalidJSON, node.getNodename());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.dtolabs.rundeck.plugins.descriptions.RenderingOptions;
import com.dtolabs.rundeck.plugins.step.PluginStepContext;
import com.dtolabs.rundeck.plugins.step.StepPlugin;
import com.fasterxml.jackson.core.JsonProcessingException;

import static com.dtolabs.rundeck.core.plugins.configuration.StringRenderingConstants.CODE_SYNTAX_MODE;
import static com.dtolabs.rundeck.core.plugins.configuration.StringRenderingConstants.DISPLAY_TYPE_KEY;
Expand Down Expand Up @@ -59,20 +60,23 @@ public class SwitchCaseStepPlugin implements StepPlugin {
@PluginProperty(title = "Test Value", description = "Test value", required = true)
private String testValue;

@PluginProperty(title = "Default", description = "Default value", required = false)
@PluginProperty(title = "Default", description = "Default value")
private String defaultValue;

@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)")
private boolean elevateToGlobal;

@Override
public void executeStep(final PluginStepContext ctx, final Map<String, Object> cfg) throws StepException {

String group = cfg.getOrDefault("group", this.group).toString();
String name = cfg.getOrDefault("name", this.name).toString();
String cases = cfg.getOrDefault("cases", this.cases).toString();
String testValue = cfg.getOrDefault("testValue", this.testValue).toString();
boolean elevateToGlobal = cfg.getOrDefault("elevateToGlobal", this.elevateToGlobal).toString().equals("true");
group = cfg.getOrDefault("group", this.group).toString();
name = cfg.getOrDefault("name", this.name).toString();
cases = cfg.getOrDefault("cases", this.cases).toString();
testValue = cfg.getOrDefault("testValue", this.testValue).toString();
if (cfg.containsKey("elevateToGlobal")) {
elevateToGlobal = cfg.get("elevateToGlobal").equals("true");
}

boolean globalHasDefault = defaultValue != null && defaultValue.length() > 0;
boolean cfgHasDefault = cfg.containsKey("defaultValue") && cfg.get("defaultValue") != null;
if (cfgHasDefault) {
Expand All @@ -82,10 +86,15 @@ public void executeStep(final PluginStepContext ctx, final Map<String, Object> c
ctx.getLogger().log(Constants.DEBUG_LEVEL,
"Setting " + group + "." + name + " based on " + testValue + " " + cases);

if (cfgHasDefault || globalHasDefault) {
(new Switch(ctx)).switchCase(group, name, cases, testValue, defaultValue, elevateToGlobal);
} else {
(new Switch(ctx)).switchCase(group, name, cases, testValue, elevateToGlobal);
try {
if (cfgHasDefault || globalHasDefault) {
(new Switch(ctx)).switchCase(group, name, cases, testValue, defaultValue, elevateToGlobal);
} else {
(new Switch(ctx)).switchCase(group, name, cases, testValue, elevateToGlobal);
}
} catch (
JsonProcessingException e) {
throw new StepException(e.getMessage(), Switch.Causes.InvalidJSON);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ public class SwitchCaseNodeStepPluginTest {

@Mock
INodeEntry node;
private final String group = "raft";
private final String name = "test";
private final String testValue = "any";
private final String defaultValue = "any";

@Before
public void setUp() {
Expand All @@ -69,7 +73,7 @@ public void setUp() {
@Test
public void runTestOne() throws NodeStepException {
Map<String, String> cases = ImmutableMap.<String, String>builder().put("k1", "v1").put("k2", "v2").build();
this.runTest("v1", "k1", cases, "any");
this.runTest("v1", "k1", cases, defaultValue);
}

@Test
Expand All @@ -81,7 +85,7 @@ public void runTestTwo() throws NodeStepException {
@Test
public void returnsDefaultOnNoMatch() throws NodeStepException {
Map<String, String> cases = ImmutableMap.<String, String>builder().put("k1", "v1").put("k2", "v2").build();
this.runTest("any", "k3", cases, "any");
this.runTest(testValue, "k3", cases, defaultValue);
}

@Test
Expand All @@ -97,10 +101,32 @@ public void runTestNoDefaultValue() throws NodeStepException {
this.runTestNoDefault(configuration);
}

@Test(expected = NodeStepException.class)
public void testInvalidCases() throws NodeStepException {
StringBuffer caseString = new StringBuffer();
Map<String, String> cases = ImmutableMap.<String, String>builder().put("k1", "v1").put("k2", "v2").build();
cases.forEach((k, v) -> caseString.append('"').append(k).append('"').append(":").append('"').append(v).append('"').append(","));
invalidInput(caseString.toString());
}

private void invalidInput(String caseString)
throws NodeStepException {

Map<String, Object> configuration = new HashMap<>();
configuration.put("group", group);
configuration.put("name", name);
configuration.put("cases", caseString);
configuration.put("testValue", testValue);
configuration.put("defaultValue", defaultValue);

when(context.getOutputContext()).thenReturn(sharedOutputContext);
when(context.getLogger()).thenReturn(logger);

this.plugin.executeNodeStep(context, configuration, node);
}

private void runTest(String expected, String testValue, Map<String, String> cases, String defaultValue)
throws NodeStepException {
String group = "raft";
String name = "test";
StringBuffer caseString = new StringBuffer();
cases.forEach((k, v) -> caseString.append('"').append(k).append('"').append(":").append('"').append(v).append('"').append(","));
caseString.setLength(caseString.length() - 1);
Expand All @@ -122,8 +148,6 @@ private void runTest(String expected, String testValue, Map<String, String> case

public void runTestNoDefault(Map<String, Object> configuration)
throws NodeStepException {
String group = "raft";
String name = "test";

Map<String, String> cases = ImmutableMap.<String, String>builder().put("k1", "v1").put("k2", "v2").build();
StringBuilder caseString = new StringBuilder();
Expand All @@ -143,4 +167,6 @@ public void runTestNoDefault(Map<String, Object> configuration)
verify(sharedOutputContext, never()).addOutput(any(String.class), any(String.class), any(String.class));
}



}

0 comments on commit 03ee493

Please sign in to comment.