From cb4d67f8f4edb8fb7ba9f663f6f12adc5530e8c1 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 16 Jan 2014 17:24:14 -0800 Subject: [PATCH] Execution output supports node and step context selection for api v10 --- .../java/org/rundeck/api/RundeckClient.java | 83 +++++++++----- .../org/rundeck/api/domain/RundeckOutput.java | 47 +++++++- .../api/domain/RundeckOutputEntry.java | 58 ++++++++-- .../rundeck/api/parser/OutputEntryParser.java | 53 ++++++++- .../org/rundeck/api/parser/OutputParser.java | 7 +- .../org/rundeck/api/RundeckClientTest.java | 101 ++++++++++++++++++ .../api/parser/OutputEntryParserTest.java | 55 ++++++++++ .../rundeck/api/parser/OutputParserTest.java | 85 +++++++++++++++ .../betamax/tapes/execution_output_basic.yaml | 24 +++++ .../tapes/execution_output_fornode.yaml | 23 ++++ .../execution_output_fornodeandstep.yaml | 23 ++++ .../tapes/execution_output_forstep.yaml | 24 +++++ .../rundeck/api/parser/output-filtered.xml | 19 ++++ .../org/rundeck/api/parser/output-state.xml | 46 ++++++++ .../rundeck/api/parser/output-unmodified.xml | 16 +++ .../org/rundeck/api/parser/output1.xml | 22 ++++ 16 files changed, 647 insertions(+), 39 deletions(-) create mode 100644 src/test/java/org/rundeck/api/parser/OutputEntryParserTest.java create mode 100644 src/test/java/org/rundeck/api/parser/OutputParserTest.java create mode 100644 src/test/resources/betamax/tapes/execution_output_basic.yaml create mode 100644 src/test/resources/betamax/tapes/execution_output_fornode.yaml create mode 100644 src/test/resources/betamax/tapes/execution_output_fornodeandstep.yaml create mode 100644 src/test/resources/betamax/tapes/execution_output_forstep.yaml create mode 100644 src/test/resources/org/rundeck/api/parser/output-filtered.xml create mode 100644 src/test/resources/org/rundeck/api/parser/output-state.xml create mode 100644 src/test/resources/org/rundeck/api/parser/output-unmodified.xml create mode 100644 src/test/resources/org/rundeck/api/parser/output1.xml diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index f705c48..6c0d248 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -3265,13 +3265,20 @@ public class RundeckClient implements Serializable { public RundeckOutput getJobExecutionOutput(Long executionId, int offset, int lastlines, long lastmod, int maxlines) throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); - return new ApiCall(this).get(new ApiPathBuilder( + ApiPathBuilder param = new ApiPathBuilder( "/execution/", executionId.toString(), "/output") - .param("offset", offset) - .param("lastlines", lastlines) - .param("lastmod", lastmod) - .param("maxlines", maxlines), + .param("offset", offset); + if (lastlines > 0) { + param.param("lastlines", lastlines); + } + if (lastmod >= 0) { + param.param("lastmod", lastmod); + } + if (maxlines > 0) { + param.param("maxlines", maxlines); + } + return new ApiCall(this).get(param, new OutputParser("result/output", createOutputEntryParser())); } @@ -3300,13 +3307,20 @@ public class RundeckClient implements Serializable { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); AssertUtil.notNull(nodeName, "nodeName is mandatory to get the output of a job execution!"); - return new ApiCall(this).get(new ApiPathBuilder( + ApiPathBuilder param = new ApiPathBuilder( "/execution/", executionId.toString(), - "/output/node/", nodeName ) - .param("offset", offset) - .param("lastlines", lastlines) - .param("lastmod", lastmod) - .param("maxlines", maxlines), + "/output/node/", nodeName) + .param("offset", offset); + if(lastlines>0) { + param.param("lastlines", lastlines); + } + if(lastmod>=0) { + param.param("lastmod", lastmod); + } + if(maxlines>0) { + param.param("maxlines", maxlines); + } + return new ApiCall(this).get(param, new OutputParser("result/output", createOutputEntryParser())); } /** @@ -3334,13 +3348,20 @@ public class RundeckClient implements Serializable { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); AssertUtil.notNull(stepCtx, "stepCtx is mandatory to get the output of a job execution!"); - return new ApiCall(this).get(new ApiPathBuilder( + ApiPathBuilder param = new ApiPathBuilder( "/execution/", executionId.toString(), "/output/step/", stepCtx) - .param("offset", offset) - .param("lastlines", lastlines) - .param("lastmod", lastmod) - .param("maxlines", maxlines), + .param("offset", offset); + if (lastlines > 0) { + param.param("lastlines", lastlines); + } + if (lastmod >= 0) { + param.param("lastmod", lastmod); + } + if (maxlines > 0) { + param.param("maxlines", maxlines); + } + return new ApiCall(this).get(param, new OutputParser("result/output", createOutputEntryParser())); } /** @@ -3369,14 +3390,21 @@ public class RundeckClient implements Serializable { AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); AssertUtil.notNull(nodeName, "nodeName is mandatory to get the output of a job execution!"); AssertUtil.notNull(stepCtx, "stepCtx is mandatory to get the output of a job execution!"); - return new ApiCall(this).get(new ApiPathBuilder( + ApiPathBuilder param = new ApiPathBuilder( "/execution/", executionId.toString(), "/output/node/", nodeName, "/step/", stepCtx) - .param("offset", offset) - .param("lastlines", lastlines) - .param("lastmod", lastmod) - .param("maxlines", maxlines), + .param("offset", offset); + if (lastlines > 0) { + param.param("lastlines", lastlines); + } + if (lastmod >= 0) { + param.param("lastmod", lastmod); + } + if (maxlines > 0) { + param.param("maxlines", maxlines); + } + return new ApiCall(this).get(param, new OutputParser("result/output", createOutputEntryParser())); } @@ -3397,10 +3425,15 @@ public class RundeckClient implements Serializable { public RundeckOutput getJobExecutionOutput(Long executionId, int offset, long lastmod, int maxlines) throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); - return new ApiCall(this).get(new ApiPathBuilder("/execution/", executionId.toString(), "/output").param("offset", offset) - .param("lastmod", lastmod) - .param("maxlines", maxlines), - new OutputParser("result/output", createOutputEntryParser())); + ApiPathBuilder param = new ApiPathBuilder("/execution/", executionId.toString(), "/output") + .param("offset", offset); + if (lastmod >= 0) { + param.param("lastmod", lastmod); + } + if (maxlines > 0) { + param.param("maxlines", maxlines); + } + return new ApiCall(this).get(param, new OutputParser("result/output", createOutputEntryParser())); } private OutputEntryParser createOutputEntryParser() { diff --git a/src/main/java/org/rundeck/api/domain/RundeckOutput.java b/src/main/java/org/rundeck/api/domain/RundeckOutput.java index a4696ec..3663810 100644 --- a/src/main/java/org/rundeck/api/domain/RundeckOutput.java +++ b/src/main/java/org/rundeck/api/domain/RundeckOutput.java @@ -22,9 +22,9 @@ public class RundeckOutput implements Serializable { //private String error = null; - private Boolean unmodified; + private Boolean unmodified = false; - private Boolean empty; + private Boolean empty = false; private int offset; @@ -46,6 +46,9 @@ public class RundeckOutput implements Serializable { List logEntries = null; + private String filterNode; + private String filterStep; + public Long getExecutionId() { return executionId; } @@ -181,6 +184,7 @@ public class RundeckOutput implements Serializable { ", execCompleted=" + execCompleted + ", hasFailedNodes=" + hasFailedNodes + ", status=" + status + ", lastModified=" + lastModified + ", execDuration=" + execDuration + ", percentLoaded=" + percentLoaded + + ", filterNode=" + filterNode + ", filterStep=" + filterStep + ", totalSize=" + totalSize + "]"; } @@ -203,6 +207,8 @@ public class RundeckOutput implements Serializable { result = prime * result + ((percentLoaded == null) ? 0 : percentLoaded.hashCode()); result = prime * result + totalSize; result = prime * result + ((logEntries == null) ? 0 : logEntries.hashCode()); + result = prime * result + ((filterNode == null) ? 0 : filterNode.hashCode()); + result = prime * result + ((filterStep == null) ? 0 : filterStep.hashCode()); return result; } @@ -286,7 +292,40 @@ public class RundeckOutput implements Serializable { return false; } else if (!logEntries.equals(other.logEntries)) return false; + if (filterNode == null) { + if (other.filterNode != null) + return false; + } else if (!filterNode.equals(other.filterNode)) + return false; + if (filterStep == null) { + if (other.filterStep != null) + return false; + } else if (!filterStep.equals(other.filterStep)) + return false; return true; } - -} \ No newline at end of file + + public String getFilterNode() { + return filterNode; + } + + /** + * return the node name used to filter this output + * @param filterNode + */ + public void setFilterNode(String filterNode) { + this.filterNode = filterNode; + } + + /** + * Return the step context used to filter this output + * @return + */ + public String getFilterStep() { + return filterStep; + } + + public void setFilterStep(String filterStep) { + this.filterStep = filterStep; + } +} diff --git a/src/main/java/org/rundeck/api/domain/RundeckOutputEntry.java b/src/main/java/org/rundeck/api/domain/RundeckOutputEntry.java index 607c01a..4160634 100644 --- a/src/main/java/org/rundeck/api/domain/RundeckOutputEntry.java +++ b/src/main/java/org/rundeck/api/domain/RundeckOutputEntry.java @@ -1,6 +1,8 @@ package org.rundeck.api.domain; import java.io.Serializable; +import java.util.Date; +import java.util.Map; /** * Represents a RunDeck output entry @@ -11,7 +13,8 @@ public class RundeckOutputEntry implements Serializable { private static final long serialVersionUID = 1L; private String time = null; - + private Date absoluteTime = null; + private RundeckLogLevel level = null; private String message = null; @@ -21,7 +24,9 @@ public class RundeckOutputEntry implements Serializable { private String command = null; private String node = null; + private String type = null; + private Map metadata; public String getTime() { @@ -77,8 +82,11 @@ public class RundeckOutputEntry implements Serializable { @Override public String toString() { return "RundeckOutputEntry [time=" + time + ", level=" + level + - ", message=" + message + ", user=" + user + ", command=" + - command + ", node=" + node + "]"; + ", message=" + message + ", user=" + user + + ", command=" + command + + ", type=" + type + + ", metadata=" + metadata + + ", node=" + node + "]"; } @Override @@ -91,6 +99,8 @@ public class RundeckOutputEntry implements Serializable { result = prime * result + ((user == null) ? 0 : user.hashCode()); result = prime * result + ((command == null) ? 0 : command.hashCode()); result = prime * result + ((node == null) ? 0 : node.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((metadata == null) ? 0 : metadata.hashCode()); return result; } @@ -134,13 +144,49 @@ public class RundeckOutputEntry implements Serializable { return false; } else if (!node.equals(other.node)) return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (metadata == null) { + if (other.metadata != null) + return false; + } else if (!metadata.equals(other.metadata)) + return false; return true; } + /** + * type of entry + */ + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Map getMetadata() { + return metadata; + } + + public void setMetadata(Map metadata) { + this.metadata = metadata; + } + + public Date getAbsoluteTime() { + return absoluteTime; + } + + public void setAbsoluteTime(Date absoluteTime) { + this.absoluteTime = absoluteTime; + } + public static enum RundeckLogLevel { - SEVERE, WARNING, INFO, CONFIG, FINEST; + SEVERE, ERROR, WARNING, INFO, NORMAL, DEBUG, CONFIG, VERBOSE, FINEST,; } - -} \ No newline at end of file +} diff --git a/src/main/java/org/rundeck/api/parser/OutputEntryParser.java b/src/main/java/org/rundeck/api/parser/OutputEntryParser.java index 9754377..36fbca8 100644 --- a/src/main/java/org/rundeck/api/parser/OutputEntryParser.java +++ b/src/main/java/org/rundeck/api/parser/OutputEntryParser.java @@ -6,6 +6,10 @@ import org.dom4j.Node; import org.rundeck.api.domain.RundeckOutputEntry; import org.rundeck.api.domain.RundeckOutputEntry.RundeckLogLevel; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + /** * Parses output message content for API v6 */ @@ -16,15 +20,28 @@ public class OutputEntryParser implements XmlNodeParser { public OutputEntryParser() { super(); + dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); } + private SimpleDateFormat dateFormat; /** * @param xpath of the event element if it is not the root node */ public OutputEntryParser(String xpath) { - super(); + this(); this.xpath = xpath; } + static HashSet nonMetaAttributes = new HashSet(); + static { + nonMetaAttributes.add("time"); + nonMetaAttributes.add("level"); + nonMetaAttributes.add("user"); + nonMetaAttributes.add("node"); + nonMetaAttributes.add("type"); + nonMetaAttributes.add("log"); + nonMetaAttributes.add("absolute_type"); + } @Override public RundeckOutputEntry parseXmlNode(Node node) { @@ -38,15 +55,45 @@ public class OutputEntryParser implements XmlNodeParser { } catch (IllegalArgumentException e) { outputEntry.setLevel(null); } + if(null!=entryNode.valueOf("@absolute_time")) { + outputEntry.setAbsoluteTime(parseDate(StringUtils.trimToNull(entryNode.valueOf("@absolute_time")))); + } outputEntry.setUser(StringUtils.trimToNull(entryNode.valueOf("@user"))); - outputEntry.setCommand(StringUtils.trimToNull(entryNode.valueOf("@command"))); outputEntry.setNode(StringUtils.trimToNull(entryNode.valueOf("@node"))); + outputEntry.setType(StringUtils.trimToNull(entryNode.valueOf("@type"))); + + HashMap meta = new HashMap(); + List list = entryNode.selectNodes("@*"); + for (Object node1 : list) { + if(node1 instanceof Node) { + Node child = (Node) node1; + if (!nonMetaAttributes.contains(child.getName())) { + meta.put(child.getName(), child.getText()); + } + } + } + if(meta.size()>0){ + outputEntry.setMetadata(meta); + } outputEntry.setMessage(parseMessage(entryNode)); return outputEntry; } + private Date parseDate(String s) { + if(null==s){ + return null; + } + try { + Date parse = dateFormat.parse(s); + System.out.println(s + ": " + parse.getTime()); + return parse; + } catch (ParseException e) { + return null; + } + } + /** * Parse the message content */ @@ -54,4 +101,4 @@ public class OutputEntryParser implements XmlNodeParser { return StringUtils.trimToNull(entryNode.valueOf("@log")); } -} \ No newline at end of file +} diff --git a/src/main/java/org/rundeck/api/parser/OutputParser.java b/src/main/java/org/rundeck/api/parser/OutputParser.java index f5fe2a2..bc988e2 100644 --- a/src/main/java/org/rundeck/api/parser/OutputParser.java +++ b/src/main/java/org/rundeck/api/parser/OutputParser.java @@ -47,6 +47,7 @@ public class OutputParser implements XmlNodeParser { output.setCompleted(Boolean.valueOf(entryNode.valueOf("completed"))); output.setExecCompleted(Boolean.valueOf(entryNode.valueOf("execCompleted"))); output.setHasFailedNodes(Boolean.valueOf(entryNode.valueOf("hasFailedNodes"))); + output.setUnmodified(Boolean.valueOf(entryNode.valueOf("unmodified"))); try { output.setStatus(RundeckExecution.ExecutionStatus @@ -78,6 +79,10 @@ public class OutputParser implements XmlNodeParser { } catch (NumberFormatException e) { output.setTotalSize(-1); } + if(entryNode.selectSingleNode("filter")!=null){ + output.setFilterNode(StringUtils.trimToNull(entryNode.valueOf("filter/@nodename"))); + output.setFilterStep(StringUtils.trimToNull(entryNode.valueOf("filter/@stepctx"))); + } Node entriesListNode = entryNode.selectSingleNode("entries"); @@ -93,4 +98,4 @@ public class OutputParser implements XmlNodeParser { return output; } -} \ No newline at end of file +} diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index c5330be..76cac2c 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -1034,6 +1034,107 @@ public class RundeckClientTest { RundeckExecution exec2 = runningExecutions.get(1); Assert.assertEquals("test2", exec2.getProject()); } + /** + * Execution output + */ + @Test + @Betamax(tape = "execution_output_basic", mode = TapeMode.READ_ONLY) + public void executionOutputBasic() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_6, 10); + RundeckOutput output = client.getJobExecutionOutput(146L,0,0L,-1); + + Assert.assertEquals(new Long(1602), output.getExecDuration()); + Assert.assertEquals(new Long(146), output.getExecutionId()); + Assert.assertEquals(new Long(1389894504000L), output.getLastModified()); + Assert.assertEquals(null, output.getFilterNode()); + Assert.assertEquals(null, output.getFilterStep()); + Assert.assertEquals(1409, output.getOffset()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, output.getStatus()); + Assert.assertEquals(new Float(99.57597), output.getPercentLoaded()); + Assert.assertEquals(1415, output.getTotalSize()); + Assert.assertEquals(true, output.isCompleted()); + Assert.assertEquals(true, output.isExecCompleted()); + Assert.assertEquals(false, output.isEmpty()); + Assert.assertEquals(false, output.isHasFailedNodes()); + Assert.assertEquals(false, output.isUnmodified()); + Assert.assertEquals(3, output.getLogEntries().size()); + } + /** + * Execution output for a node + */ + @Test + @Betamax(tape = "execution_output_fornode", mode = TapeMode.READ_ONLY) + public void executionOutputForNode() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_6, 10); + RundeckOutput output = client.getJobExecutionOutputForNode(146L,"node-14.qa.subgroup.mycompany.com",0,-1,0L,-1); + + Assert.assertEquals(new Long(1602), output.getExecDuration()); + Assert.assertEquals(new Long(146), output.getExecutionId()); + Assert.assertEquals(new Long(1389894504000L), output.getLastModified()); + Assert.assertEquals("node-14.qa.subgroup.mycompany.com", output.getFilterNode()); + Assert.assertEquals(null, output.getFilterStep()); + Assert.assertEquals(1409, output.getOffset()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, output.getStatus()); + Assert.assertEquals(new Float(99.57597), output.getPercentLoaded()); + Assert.assertEquals(1415, output.getTotalSize()); + Assert.assertEquals(true, output.isCompleted()); + Assert.assertEquals(true, output.isExecCompleted()); + Assert.assertEquals(false, output.isEmpty()); + Assert.assertEquals(false, output.isHasFailedNodes()); + Assert.assertEquals(false, output.isUnmodified()); + Assert.assertEquals(1, output.getLogEntries().size()); + } + /** + * Execution output for a step + */ + @Test + @Betamax(tape = "execution_output_forstep", mode = TapeMode.READ_ONLY) + public void executionOutputForStep() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_6, 10); + RundeckOutput output = client.getJobExecutionOutputForStep(146L,"1",0,-1,0L,-1); + + Assert.assertEquals(new Long(1602), output.getExecDuration()); + Assert.assertEquals(new Long(146), output.getExecutionId()); + Assert.assertEquals(new Long(1389894504000L), output.getLastModified()); + Assert.assertEquals(null, output.getFilterNode()); + Assert.assertEquals("1", output.getFilterStep()); + Assert.assertEquals(1409, output.getOffset()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, output.getStatus()); + Assert.assertEquals(new Float(99.57597), output.getPercentLoaded()); + Assert.assertEquals(1415, output.getTotalSize()); + Assert.assertEquals(true, output.isCompleted()); + Assert.assertEquals(true, output.isExecCompleted()); + Assert.assertEquals(false, output.isEmpty()); + Assert.assertEquals(false, output.isHasFailedNodes()); + Assert.assertEquals(false, output.isUnmodified()); + Assert.assertEquals(3, output.getLogEntries().size()); + } + + /** + * Execution output for a node and step + */ + @Test + @Betamax(tape = "execution_output_fornodeandstep", mode = TapeMode.READ_ONLY) + public void executionOutputForNodeAndStep() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_6, 10); + RundeckOutput output = client.getJobExecutionOutputForNodeAndStep(146L,"node-14.qa.subgroup.mycompany.com","1",0,-1,0L,-1); + + Assert.assertEquals(new Long(1602), output.getExecDuration()); + Assert.assertEquals(new Long(146), output.getExecutionId()); + Assert.assertEquals(new Long(1389894504000L), output.getLastModified()); + Assert.assertEquals("node-14.qa.subgroup.mycompany.com", output.getFilterNode()); + Assert.assertEquals("1", output.getFilterStep()); + Assert.assertEquals(1409, output.getOffset()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, output.getStatus()); + Assert.assertEquals(new Float(99.57597), output.getPercentLoaded()); + Assert.assertEquals(1415, output.getTotalSize()); + Assert.assertEquals(true, output.isCompleted()); + Assert.assertEquals(true, output.isExecCompleted()); + Assert.assertEquals(false, output.isEmpty()); + Assert.assertEquals(false, output.isHasFailedNodes()); + Assert.assertEquals(false, output.isUnmodified()); + Assert.assertEquals(1, output.getLogEntries().size()); + } @Before public void setUp() throws Exception { diff --git a/src/test/java/org/rundeck/api/parser/OutputEntryParserTest.java b/src/test/java/org/rundeck/api/parser/OutputEntryParserTest.java new file mode 100644 index 0000000..40b1155 --- /dev/null +++ b/src/test/java/org/rundeck/api/parser/OutputEntryParserTest.java @@ -0,0 +1,55 @@ +package org.rundeck.api.parser; + +import org.dom4j.Document; +import org.junit.Assert; +import org.junit.Test; +import org.rundeck.api.domain.RundeckOutputEntry; + +import java.io.InputStream; +import java.util.Date; + +/** + * $INTERFACE is ... User: greg Date: 1/16/14 Time: 4:35 PM + */ +public class OutputEntryParserTest { + @Test + public void testEntryBasic() { + InputStream input = getClass().getResourceAsStream("output1.xml"); + Document document = ParserHelper.loadDocument(input); + OutputEntryParser outputEntryParser = new OutputEntryParser("//entry[1]"); + + RundeckOutputEntry rundeckOutputEntry = outputEntryParser.parseXmlNode(document); + Assert.assertEquals("hi there", rundeckOutputEntry.getMessage()); + Assert.assertEquals(null, rundeckOutputEntry.getCommand()); + Assert.assertEquals(RundeckOutputEntry.RundeckLogLevel.NORMAL, rundeckOutputEntry.getLevel()); + Assert.assertEquals("node-111.qa.subgroup.mycompany.com", rundeckOutputEntry.getNode()); + Assert.assertEquals("09:48:23", rundeckOutputEntry.getTime()); + Assert.assertEquals(new Date(1389894503000L), rundeckOutputEntry.getAbsoluteTime()); + Assert.assertEquals(null, rundeckOutputEntry.getType()); + Assert.assertEquals("Raif", rundeckOutputEntry.getUser()); + Assert.assertNotNull(rundeckOutputEntry.getMetadata()); + Assert.assertNotNull(rundeckOutputEntry.getMetadata().get("stepctx")); + Assert.assertEquals("1",rundeckOutputEntry.getMetadata().get("stepctx")); + } + @Test + public void testEntryState() { + InputStream input = getClass().getResourceAsStream("output-state.xml"); + Document document = ParserHelper.loadDocument(input); + OutputEntryParser outputEntryParser = new OutputEntryParser("//entry[1]"); + + RundeckOutputEntry rundeckOutputEntry = outputEntryParser.parseXmlNode(document); + Assert.assertEquals(null, rundeckOutputEntry.getMessage()); + Assert.assertEquals(null, rundeckOutputEntry.getCommand()); + Assert.assertEquals(RundeckOutputEntry.RundeckLogLevel.NORMAL, rundeckOutputEntry.getLevel()); + Assert.assertEquals("dignan", rundeckOutputEntry.getNode()); + Assert.assertEquals("09:48:23", rundeckOutputEntry.getTime()); + Assert.assertEquals(new Date(1389894503000L), rundeckOutputEntry.getAbsoluteTime()); + Assert.assertEquals("stepbegin", rundeckOutputEntry.getType()); + Assert.assertEquals("admin", rundeckOutputEntry.getUser()); + Assert.assertNotNull(rundeckOutputEntry.getMetadata()); + Assert.assertNotNull(rundeckOutputEntry.getMetadata().get("stepctx")); + Assert.assertEquals("1",rundeckOutputEntry.getMetadata().get("stepctx")); + Assert.assertNotNull(rundeckOutputEntry.getMetadata().get("step")); + Assert.assertEquals("1",rundeckOutputEntry.getMetadata().get("step")); + } +} diff --git a/src/test/java/org/rundeck/api/parser/OutputParserTest.java b/src/test/java/org/rundeck/api/parser/OutputParserTest.java new file mode 100644 index 0000000..dec471a --- /dev/null +++ b/src/test/java/org/rundeck/api/parser/OutputParserTest.java @@ -0,0 +1,85 @@ +package org.rundeck.api.parser; + +import org.dom4j.Document; +import org.junit.Assert; +import org.junit.Test; +import org.rundeck.api.domain.RundeckExecution; +import org.rundeck.api.domain.RundeckOutput; +import org.rundeck.api.domain.RundeckProject; + +import java.io.InputStream; + +/** + * $INTERFACE is ... User: greg Date: 1/16/14 Time: 4:24 PM + */ +public class OutputParserTest { + @Test + public void parseOutputBasic() throws Exception { + InputStream input = getClass().getResourceAsStream("output1.xml"); + Document document = ParserHelper.loadDocument(input); + + RundeckOutput output = new OutputParser("result/output", new OutputEntryParser()).parseXmlNode(document); + + Assert.assertEquals(new Long(1602), output.getExecDuration()); + Assert.assertEquals(new Long(146), output.getExecutionId()); + Assert.assertEquals(new Long(1389894504000L), output.getLastModified()); + Assert.assertEquals(null, output.getFilterNode()); + Assert.assertEquals(null, output.getFilterStep()); + Assert.assertEquals(1409, output.getOffset()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, output.getStatus()); + Assert.assertEquals(new Float(99.9), output.getPercentLoaded()); + Assert.assertEquals(1415, output.getTotalSize()); + Assert.assertEquals(true, output.isCompleted()); + Assert.assertEquals(true, output.isExecCompleted()); + Assert.assertEquals(false, output.isEmpty()); + Assert.assertEquals(false, output.isHasFailedNodes()); + Assert.assertEquals(false, output.isUnmodified()); + Assert.assertEquals(3, output.getLogEntries().size()); + } + @Test + public void parseOutputFiltered() throws Exception { + InputStream input = getClass().getResourceAsStream("output-filtered.xml"); + Document document = ParserHelper.loadDocument(input); + + RundeckOutput output = new OutputParser("result/output", new OutputEntryParser()).parseXmlNode(document); + + Assert.assertEquals(new Long(1602), output.getExecDuration()); + Assert.assertEquals(new Long(146), output.getExecutionId()); + Assert.assertEquals(new Long(1389894504000L), output.getLastModified()); + Assert.assertEquals("node-111.qa.subgroup.mycompany.com", output.getFilterNode()); + Assert.assertEquals("1", output.getFilterStep()); + Assert.assertEquals(1409, output.getOffset()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, output.getStatus()); + Assert.assertEquals(new Float(99.9), output.getPercentLoaded()); + Assert.assertEquals(1415, output.getTotalSize()); + Assert.assertEquals(true, output.isCompleted()); + Assert.assertEquals(true, output.isExecCompleted()); + Assert.assertEquals(false, output.isEmpty()); + Assert.assertEquals(false, output.isHasFailedNodes()); + Assert.assertEquals(false, output.isUnmodified()); + Assert.assertEquals(1, output.getLogEntries().size()); + } + @Test + public void parseOutputUnmodified() throws Exception { + InputStream input = getClass().getResourceAsStream("output-unmodified.xml"); + Document document = ParserHelper.loadDocument(input); + + RundeckOutput output = new OutputParser("result/output", new OutputEntryParser()).parseXmlNode(document); + + Assert.assertEquals(new Long(1602), output.getExecDuration()); + Assert.assertEquals(new Long(146), output.getExecutionId()); + Assert.assertEquals(new Long(1389894504000L), output.getLastModified()); + Assert.assertEquals(null, output.getFilterNode()); + Assert.assertEquals(null, output.getFilterStep()); + Assert.assertEquals(0, output.getOffset()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, output.getStatus()); + Assert.assertEquals(null, output.getPercentLoaded()); + Assert.assertEquals(1415, output.getTotalSize()); + Assert.assertEquals(true, output.isCompleted()); + Assert.assertEquals(true, output.isExecCompleted()); + Assert.assertEquals(false, output.isEmpty()); + Assert.assertEquals(false, output.isHasFailedNodes()); + Assert.assertEquals(true, output.isUnmodified()); + Assert.assertEquals(null, output.getLogEntries()); + } +} diff --git a/src/test/resources/betamax/tapes/execution_output_basic.yaml b/src/test/resources/betamax/tapes/execution_output_basic.yaml new file mode 100644 index 0000000..9315e74 --- /dev/null +++ b/src/test/resources/betamax/tapes/execution_output_basic.yaml @@ -0,0 +1,24 @@ +!tape +name: execution_output_basic +interactions: +- recorded: 2014-01-17T01:12:05.218Z + request: + method: GET + uri: http://rundeck.local:4440/api/10/execution/146/output?offset=0&lastmod=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 10 + X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1lnnniwx8tih2ehakkgipuyra;Path=/ + body: "\n \n 146\n 1409\n true\n true\n false\n succeeded\n\ + \ 1389894504000\n 1602\n 99.57597173144876\n 1415\n \n \n \n \n \n \n" diff --git a/src/test/resources/betamax/tapes/execution_output_fornode.yaml b/src/test/resources/betamax/tapes/execution_output_fornode.yaml new file mode 100644 index 0000000..3e62254 --- /dev/null +++ b/src/test/resources/betamax/tapes/execution_output_fornode.yaml @@ -0,0 +1,23 @@ +!tape +name: execution_output_fornode +interactions: +- recorded: 2014-01-17T01:07:39.379Z + request: + method: GET + uri: http://rundeck.local:4440/api/10/execution/146/output/node/node-14.qa.subgroup.mycompany.com?offset=0&lastmod=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 10 + X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=17y6a48eoxo7w4eqjrnba9xzz;Path=/ + body: "\n \n 146\n 1409\n true\n true\n false\n succeeded\n\ + \ 1389894504000\n 1602\n 99.57597173144876\n 1415\n \n \n\ + \ \n \n \n" diff --git a/src/test/resources/betamax/tapes/execution_output_fornodeandstep.yaml b/src/test/resources/betamax/tapes/execution_output_fornodeandstep.yaml new file mode 100644 index 0000000..1c5d5fa --- /dev/null +++ b/src/test/resources/betamax/tapes/execution_output_fornodeandstep.yaml @@ -0,0 +1,23 @@ +!tape +name: execution_output_fornodeandstep +interactions: +- recorded: 2014-01-17T01:21:20.524Z + request: + method: GET + uri: http://rundeck.local:4440/api/10/execution/146/output/node/node-14.qa.subgroup.mycompany.com/step/1?offset=0&lastmod=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 10 + X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1tik7xow5yg5t1avvahzumv6u1;Path=/ + body: "\n \n 146\n 1409\n true\n true\n false\n succeeded\n\ + \ 1389894504000\n 1602\n 99.57597173144876\n 1415\n \n \ + \ \n \n \n \n" diff --git a/src/test/resources/betamax/tapes/execution_output_forstep.yaml b/src/test/resources/betamax/tapes/execution_output_forstep.yaml new file mode 100644 index 0000000..974d04e --- /dev/null +++ b/src/test/resources/betamax/tapes/execution_output_forstep.yaml @@ -0,0 +1,24 @@ +!tape +name: execution_output_forstep +interactions: +- recorded: 2014-01-17T01:10:44.001Z + request: + method: GET + uri: http://rundeck.local:4440/api/10/execution/146/output/step/1?offset=0&lastmod=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 10 + X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=37vkq48ddskqv2f3etipviu8;Path=/ + body: "\n \n 146\n 1409\n true\n true\n false\n succeeded\n\ + \ 1389894504000\n 1602\n 99.57597173144876\n 1415\n \n \n \n \n \n \n \n" diff --git a/src/test/resources/org/rundeck/api/parser/output-filtered.xml b/src/test/resources/org/rundeck/api/parser/output-filtered.xml new file mode 100644 index 0000000..9d2fb98 --- /dev/null +++ b/src/test/resources/org/rundeck/api/parser/output-filtered.xml @@ -0,0 +1,19 @@ + + + 146 + 1409 + true + true + false + succeeded + 1389894504000 + 1602 + 99.9 + 1415 + + + + + + diff --git a/src/test/resources/org/rundeck/api/parser/output-state.xml b/src/test/resources/org/rundeck/api/parser/output-state.xml new file mode 100644 index 0000000..c0210d7 --- /dev/null +++ b/src/test/resources/org/rundeck/api/parser/output-state.xml @@ -0,0 +1,46 @@ + + + 146 + 1409 + true + true + false + succeeded + 1389894504000 + 1602 + 99.57597173144876 + 1415 + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/org/rundeck/api/parser/output-unmodified.xml b/src/test/resources/org/rundeck/api/parser/output-unmodified.xml new file mode 100644 index 0000000..dc4fad9 --- /dev/null +++ b/src/test/resources/org/rundeck/api/parser/output-unmodified.xml @@ -0,0 +1,16 @@ + + + 146 + 0 + true + true + Unmodified + true + false + succeeded + 1389894504000 + 1602 + 1415 + + + diff --git a/src/test/resources/org/rundeck/api/parser/output1.xml b/src/test/resources/org/rundeck/api/parser/output1.xml new file mode 100644 index 0000000..89f508a --- /dev/null +++ b/src/test/resources/org/rundeck/api/parser/output1.xml @@ -0,0 +1,22 @@ + + + 146 + 1409 + true + true + false + succeeded + 1389894504000 + 1602 + 99.9 + 1415 + + + + + + +