Execution output supports node and step context selection for api v10

This commit is contained in:
Greg Schueler 2014-01-16 17:24:14 -08:00
parent 8e59972a79
commit cb4d67f8f4
16 changed files with 647 additions and 39 deletions

View file

@ -3265,13 +3265,20 @@ public class RundeckClient implements Serializable {
public RundeckOutput getJobExecutionOutput(Long executionId, int offset, int lastlines, long lastmod, int maxlines) public RundeckOutput getJobExecutionOutput(Long executionId, int offset, int lastlines, long lastmod, int maxlines)
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); 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(), "/execution/", executionId.toString(),
"/output") "/output")
.param("offset", offset) .param("offset", offset);
.param("lastlines", lastlines) if (lastlines > 0) {
.param("lastmod", lastmod) param.param("lastlines", lastlines);
.param("maxlines", maxlines), }
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())); new OutputParser("result/output", createOutputEntryParser()));
} }
@ -3300,13 +3307,20 @@ public class RundeckClient implements Serializable {
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); 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(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(), "/execution/", executionId.toString(),
"/output/node/", nodeName ) "/output/node/", nodeName)
.param("offset", offset) .param("offset", offset);
.param("lastlines", lastlines) if(lastlines>0) {
.param("lastmod", lastmod) param.param("lastlines", lastlines);
.param("maxlines", maxlines), }
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())); new OutputParser("result/output", createOutputEntryParser()));
} }
/** /**
@ -3334,13 +3348,20 @@ public class RundeckClient implements Serializable {
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); 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!"); 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(), "/execution/", executionId.toString(),
"/output/step/", stepCtx) "/output/step/", stepCtx)
.param("offset", offset) .param("offset", offset);
.param("lastlines", lastlines) if (lastlines > 0) {
.param("lastmod", lastmod) param.param("lastlines", lastlines);
.param("maxlines", maxlines), }
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())); 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(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(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!"); 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(), "/execution/", executionId.toString(),
"/output/node/", nodeName, "/output/node/", nodeName,
"/step/", stepCtx) "/step/", stepCtx)
.param("offset", offset) .param("offset", offset);
.param("lastlines", lastlines) if (lastlines > 0) {
.param("lastmod", lastmod) param.param("lastlines", lastlines);
.param("maxlines", maxlines), }
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())); 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) public RundeckOutput getJobExecutionOutput(Long executionId, int offset, long lastmod, int maxlines)
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notNull(executionId, "executionId is mandatory to get the output of a job execution!"); 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) ApiPathBuilder param = new ApiPathBuilder("/execution/", executionId.toString(), "/output")
.param("lastmod", lastmod) .param("offset", offset);
.param("maxlines", maxlines), if (lastmod >= 0) {
new OutputParser("result/output", createOutputEntryParser())); 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() { private OutputEntryParser createOutputEntryParser() {

View file

@ -22,9 +22,9 @@ public class RundeckOutput implements Serializable {
//private String error = null; //private String error = null;
private Boolean unmodified; private Boolean unmodified = false;
private Boolean empty; private Boolean empty = false;
private int offset; private int offset;
@ -46,6 +46,9 @@ public class RundeckOutput implements Serializable {
List<RundeckOutputEntry> logEntries = null; List<RundeckOutputEntry> logEntries = null;
private String filterNode;
private String filterStep;
public Long getExecutionId() { public Long getExecutionId() {
return executionId; return executionId;
} }
@ -181,6 +184,7 @@ public class RundeckOutput implements Serializable {
", execCompleted=" + execCompleted + ", hasFailedNodes=" + hasFailedNodes + ", execCompleted=" + execCompleted + ", hasFailedNodes=" + hasFailedNodes +
", status=" + status + ", lastModified=" + lastModified + ", status=" + status + ", lastModified=" + lastModified +
", execDuration=" + execDuration + ", percentLoaded=" + percentLoaded + ", execDuration=" + execDuration + ", percentLoaded=" + percentLoaded +
", filterNode=" + filterNode + ", filterStep=" + filterStep +
", totalSize=" + totalSize + "]"; ", totalSize=" + totalSize + "]";
} }
@ -203,6 +207,8 @@ public class RundeckOutput implements Serializable {
result = prime * result + ((percentLoaded == null) ? 0 : percentLoaded.hashCode()); result = prime * result + ((percentLoaded == null) ? 0 : percentLoaded.hashCode());
result = prime * result + totalSize; result = prime * result + totalSize;
result = prime * result + ((logEntries == null) ? 0 : logEntries.hashCode()); 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; return result;
} }
@ -286,7 +292,40 @@ public class RundeckOutput implements Serializable {
return false; return false;
} else if (!logEntries.equals(other.logEntries)) } else if (!logEntries.equals(other.logEntries))
return false; 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; return true;
} }
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;
}
} }

View file

@ -1,6 +1,8 @@
package org.rundeck.api.domain; package org.rundeck.api.domain;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.Map;
/** /**
* Represents a RunDeck output entry * Represents a RunDeck output entry
@ -11,6 +13,7 @@ public class RundeckOutputEntry implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private String time = null; private String time = null;
private Date absoluteTime = null;
private RundeckLogLevel level = null; private RundeckLogLevel level = null;
@ -21,7 +24,9 @@ public class RundeckOutputEntry implements Serializable {
private String command = null; private String command = null;
private String node = null; private String node = null;
private String type = null;
private Map<String,String> metadata;
public String getTime() { public String getTime() {
@ -77,8 +82,11 @@ public class RundeckOutputEntry implements Serializable {
@Override @Override
public String toString() { public String toString() {
return "RundeckOutputEntry [time=" + time + ", level=" + level + return "RundeckOutputEntry [time=" + time + ", level=" + level +
", message=" + message + ", user=" + user + ", command=" + ", message=" + message + ", user=" + user
command + ", node=" + node + "]"; + ", command=" + command
+ ", type=" + type
+ ", metadata=" + metadata
+ ", node=" + node + "]";
} }
@Override @Override
@ -91,6 +99,8 @@ public class RundeckOutputEntry implements Serializable {
result = prime * result + ((user == null) ? 0 : user.hashCode()); result = prime * result + ((user == null) ? 0 : user.hashCode());
result = prime * result + ((command == null) ? 0 : command.hashCode()); result = prime * result + ((command == null) ? 0 : command.hashCode());
result = prime * result + ((node == null) ? 0 : node.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; return result;
} }
@ -134,13 +144,49 @@ public class RundeckOutputEntry implements Serializable {
return false; return false;
} else if (!node.equals(other.node)) } else if (!node.equals(other.node))
return false; 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; return true;
} }
/**
* type of entry
*/
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Map<String, String> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}
public Date getAbsoluteTime() {
return absoluteTime;
}
public void setAbsoluteTime(Date absoluteTime) {
this.absoluteTime = absoluteTime;
}
public static enum RundeckLogLevel { public static enum RundeckLogLevel {
SEVERE, WARNING, INFO, CONFIG, FINEST; SEVERE, ERROR, WARNING, INFO, NORMAL, DEBUG, CONFIG, VERBOSE, FINEST,;
} }
} }

View file

@ -6,6 +6,10 @@ import org.dom4j.Node;
import org.rundeck.api.domain.RundeckOutputEntry; import org.rundeck.api.domain.RundeckOutputEntry;
import org.rundeck.api.domain.RundeckOutputEntry.RundeckLogLevel; 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 * Parses output message content for API v6
*/ */
@ -16,15 +20,28 @@ public class OutputEntryParser implements XmlNodeParser<RundeckOutputEntry> {
public OutputEntryParser() { public OutputEntryParser() {
super(); 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 * @param xpath of the event element if it is not the root node
*/ */
public OutputEntryParser(String xpath) { public OutputEntryParser(String xpath) {
super(); this();
this.xpath = xpath; this.xpath = xpath;
} }
static HashSet<String> nonMetaAttributes = new HashSet<String>();
static {
nonMetaAttributes.add("time");
nonMetaAttributes.add("level");
nonMetaAttributes.add("user");
nonMetaAttributes.add("node");
nonMetaAttributes.add("type");
nonMetaAttributes.add("log");
nonMetaAttributes.add("absolute_type");
}
@Override @Override
public RundeckOutputEntry parseXmlNode(Node node) { public RundeckOutputEntry parseXmlNode(Node node) {
@ -38,15 +55,45 @@ public class OutputEntryParser implements XmlNodeParser<RundeckOutputEntry> {
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
outputEntry.setLevel(null); 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.setUser(StringUtils.trimToNull(entryNode.valueOf("@user")));
outputEntry.setCommand(StringUtils.trimToNull(entryNode.valueOf("@command")));
outputEntry.setNode(StringUtils.trimToNull(entryNode.valueOf("@node"))); outputEntry.setNode(StringUtils.trimToNull(entryNode.valueOf("@node")));
outputEntry.setType(StringUtils.trimToNull(entryNode.valueOf("@type")));
HashMap<String, String> meta = new HashMap<String, String>();
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)); outputEntry.setMessage(parseMessage(entryNode));
return outputEntry; 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 * Parse the message content
*/ */

View file

@ -47,6 +47,7 @@ public class OutputParser implements XmlNodeParser<RundeckOutput> {
output.setCompleted(Boolean.valueOf(entryNode.valueOf("completed"))); output.setCompleted(Boolean.valueOf(entryNode.valueOf("completed")));
output.setExecCompleted(Boolean.valueOf(entryNode.valueOf("execCompleted"))); output.setExecCompleted(Boolean.valueOf(entryNode.valueOf("execCompleted")));
output.setHasFailedNodes(Boolean.valueOf(entryNode.valueOf("hasFailedNodes"))); output.setHasFailedNodes(Boolean.valueOf(entryNode.valueOf("hasFailedNodes")));
output.setUnmodified(Boolean.valueOf(entryNode.valueOf("unmodified")));
try { try {
output.setStatus(RundeckExecution.ExecutionStatus output.setStatus(RundeckExecution.ExecutionStatus
@ -78,6 +79,10 @@ public class OutputParser implements XmlNodeParser<RundeckOutput> {
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
output.setTotalSize(-1); 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"); Node entriesListNode = entryNode.selectSingleNode("entries");

View file

@ -1034,6 +1034,107 @@ public class RundeckClientTest {
RundeckExecution exec2 = runningExecutions.get(1); RundeckExecution exec2 = runningExecutions.get(1);
Assert.assertEquals("test2", exec2.getProject()); 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 @Before
public void setUp() throws Exception { public void setUp() throws Exception {

View file

@ -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"));
}
}

View file

@ -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());
}
}

View file

@ -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: "<result success='true' apiversion='10'>\n <output>\n <id>146</id>\n <offset>1409</offset>\n <completed>true</completed>\n <execCompleted>true</execCompleted>\n <hasFailedNodes>false</hasFailedNodes>\n <execState>succeeded</execState>\n\
\ <lastModified>1389894504000</lastModified>\n <execDuration>1602</execDuration>\n <percentLoaded>99.57597173144876</percentLoaded>\n <totalSize>1415</totalSize>\n <entries>\n <entry time='09:48:23' absolute_time='2014-01-16T17:48:23Z'\
\ log='hi there' level='NORMAL' user='Raif' command='' stepctx='1' node='node-111.qa.subgroup.mycompany.com' />\n <entry time='09:48:23' absolute_time='2014-01-16T17:48:23Z' log='hi there' level='NORMAL' user='Dale' command='' stepctx='1' node='node-14.qa.subgroup.mycompany.com'\
\ />\n <entry time='09:48:24' absolute_time='2014-01-16T17:48:24Z' log='hi there' level='NORMAL' user='Carolyn' command='' stepctx='1' node='node-6.qa.subgroup.mycompany.com' />\n </entries>\n </output>\n</result>"

View file

@ -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: "<result success='true' apiversion='10'>\n <output>\n <id>146</id>\n <offset>1409</offset>\n <completed>true</completed>\n <execCompleted>true</execCompleted>\n <hasFailedNodes>false</hasFailedNodes>\n <execState>succeeded</execState>\n\
\ <lastModified>1389894504000</lastModified>\n <execDuration>1602</execDuration>\n <percentLoaded>99.57597173144876</percentLoaded>\n <totalSize>1415</totalSize>\n <filter nodename='node-14.qa.subgroup.mycompany.com' />\n <entries>\n\
\ <entry time='09:48:23' absolute_time='2014-01-16T17:48:23Z' log='hi there' level='NORMAL' user='Dale' command='' stepctx='1' node='node-14.qa.subgroup.mycompany.com' />\n </entries>\n </output>\n</result>"

View file

@ -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: "<result success='true' apiversion='10'>\n <output>\n <id>146</id>\n <offset>1409</offset>\n <completed>true</completed>\n <execCompleted>true</execCompleted>\n <hasFailedNodes>false</hasFailedNodes>\n <execState>succeeded</execState>\n\
\ <lastModified>1389894504000</lastModified>\n <execDuration>1602</execDuration>\n <percentLoaded>99.57597173144876</percentLoaded>\n <totalSize>1415</totalSize>\n <filter nodename='node-14.qa.subgroup.mycompany.com' stepctx='1' />\n \
\ <entries>\n <entry time='09:48:23' absolute_time='2014-01-16T17:48:23Z' log='hi there' level='NORMAL' user='Dale' command='' stepctx='1' node='node-14.qa.subgroup.mycompany.com' />\n </entries>\n </output>\n</result>"

View file

@ -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: "<result success='true' apiversion='10'>\n <output>\n <id>146</id>\n <offset>1409</offset>\n <completed>true</completed>\n <execCompleted>true</execCompleted>\n <hasFailedNodes>false</hasFailedNodes>\n <execState>succeeded</execState>\n\
\ <lastModified>1389894504000</lastModified>\n <execDuration>1602</execDuration>\n <percentLoaded>99.57597173144876</percentLoaded>\n <totalSize>1415</totalSize>\n <filter stepctx='1' />\n <entries>\n <entry time='09:48:23' absolute_time='2014-01-16T17:48:23Z'\
\ log='hi there' level='NORMAL' user='Raif' command='' stepctx='1' node='node-111.qa.subgroup.mycompany.com' />\n <entry time='09:48:23' absolute_time='2014-01-16T17:48:23Z' log='hi there' level='NORMAL' user='Dale' command='' stepctx='1' node='node-14.qa.subgroup.mycompany.com'\
\ />\n <entry time='09:48:24' absolute_time='2014-01-16T17:48:24Z' log='hi there' level='NORMAL' user='Carolyn' command='' stepctx='1' node='node-6.qa.subgroup.mycompany.com' />\n </entries>\n </output>\n</result>"

View file

@ -0,0 +1,19 @@
<result success="true" apiversion="10">
<output>
<id>146</id>
<offset>1409</offset>
<completed>true</completed>
<execCompleted>true</execCompleted>
<hasFailedNodes>false</hasFailedNodes>
<execState>succeeded</execState>
<lastModified>1389894504000</lastModified>
<execDuration>1602</execDuration>
<percentLoaded>99.9</percentLoaded>
<totalSize>1415</totalSize>
<filter nodename="node-111.qa.subgroup.mycompany.com" stepctx="1"/>
<entries>
<entry time="09:48:23" absolute_time="2014-01-16T17:48:23Z" log="hi there" level="NORMAL" user="Raif"
command="" stepctx="1" node="node-111.qa.subgroup.mycompany.com"/>
</entries>
</output>
</result>

View file

@ -0,0 +1,46 @@
<result success="true" apiversion="10">
<output>
<id>146</id>
<offset>1409</offset>
<completed>true</completed>
<execCompleted>true</execCompleted>
<hasFailedNodes>false</hasFailedNodes>
<execState>succeeded</execState>
<lastModified>1389894504000</lastModified>
<execDuration>1602</execDuration>
<percentLoaded>99.57597173144876</percentLoaded>
<totalSize>1415</totalSize>
<entries>
<entry node="dignan" step="1" stepctx="1" user="admin" time="09:48:23" level="NORMAL" type="stepbegin"
absolute_time="2014-01-16T17:48:23Z" log=""/>
<entry node="node-111.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Raif" time="09:48:23"
level="NORMAL" type="nodebegin" absolute_time="2014-01-16T17:48:23Z" log=""/>
<entry node="node-111.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Raif" time="09:48:23"
level="NORMAL" type="log" absolute_time="2014-01-16T17:48:23Z" log="hi there"/>
<entry node="node-111.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Raif" time="09:48:23"
level="NORMAL" type="nodeend" absolute_time="2014-01-16T17:48:23Z" log=""/>
<entry node="dignan" step="1" stepctx="1" user="admin" time="09:48:23" level="NORMAL" type="stepend"
absolute_time="2014-01-16T17:48:23Z" log=""/>
<entry node="dignan" step="1" stepctx="1" user="admin" time="09:48:23" level="NORMAL" type="stepbegin"
absolute_time="2014-01-16T17:48:23Z" log=""/>
<entry node="node-14.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Dale" time="09:48:23"
level="NORMAL" type="nodebegin" absolute_time="2014-01-16T17:48:23Z" log=""/>
<entry node="node-14.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Dale" time="09:48:23"
level="NORMAL" type="log" absolute_time="2014-01-16T17:48:23Z" log="hi there"/>
<entry node="node-14.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Dale" time="09:48:24"
level="NORMAL" type="nodeend" absolute_time="2014-01-16T17:48:24Z" log=""/>
<entry node="dignan" step="1" stepctx="1" user="admin" time="09:48:24" level="NORMAL" type="stepend"
absolute_time="2014-01-16T17:48:24Z" log=""/>
<entry node="dignan" step="1" stepctx="1" user="admin" time="09:48:24" level="NORMAL" type="stepbegin"
absolute_time="2014-01-16T17:48:24Z" log=""/>
<entry node="node-6.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Carolyn" time="09:48:24"
level="NORMAL" type="nodebegin" absolute_time="2014-01-16T17:48:24Z" log=""/>
<entry node="node-6.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Carolyn" time="09:48:24"
level="NORMAL" type="log" absolute_time="2014-01-16T17:48:24Z" log="hi there"/>
<entry node="node-6.qa.subgroup.mycompany.com" step="1" stepctx="1" user="Carolyn" time="09:48:24"
level="NORMAL" type="nodeend" absolute_time="2014-01-16T17:48:24Z" log=""/>
<entry node="dignan" step="1" stepctx="1" user="admin" time="09:48:24" level="NORMAL" type="stepend"
absolute_time="2014-01-16T17:48:24Z" log=""/>
</entries>
</output>
</result>

View file

@ -0,0 +1,16 @@
<result success="true" apiversion="10">
<output>
<id>146</id>
<offset>0</offset>
<completed>true</completed>
<unmodified>true</unmodified>
<message>Unmodified</message>
<execCompleted>true</execCompleted>
<hasFailedNodes>false</hasFailedNodes>
<execState>succeeded</execState>
<lastModified>1389894504000</lastModified>
<execDuration>1602</execDuration>
<totalSize>1415</totalSize>
<entries/>
</output>
</result>

View file

@ -0,0 +1,22 @@
<result success="true" apiversion="10">
<output>
<id>146</id>
<offset>1409</offset>
<completed>true</completed>
<execCompleted>true</execCompleted>
<hasFailedNodes>false</hasFailedNodes>
<execState>succeeded</execState>
<lastModified>1389894504000</lastModified>
<execDuration>1602</execDuration>
<percentLoaded>99.9</percentLoaded>
<totalSize>1415</totalSize>
<entries>
<entry time="09:48:23" absolute_time="2014-01-16T17:48:23Z" log="hi there" level="NORMAL" user="Raif"
command="" stepctx="1" node="node-111.qa.subgroup.mycompany.com"/>
<entry time="09:48:23" absolute_time="2014-01-16T17:48:23Z" log="hi there" level="NORMAL" user="Dale"
command="" stepctx="1" node="node-14.qa.subgroup.mycompany.com"/>
<entry time="09:48:24" absolute_time="2014-01-16T17:48:24Z" log="hi there" level="NORMAL" user="Carolyn"
command="" stepctx="1" node="node-6.qa.subgroup.mycompany.com"/>
</entries>
</output>
</result>