From e3291e3dab8f02c691ae30129756738376d49a5e Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 16 Jan 2014 15:12:38 -0800 Subject: [PATCH] Support successfulNodes/failedNodes in execution data for api v10 --- .../rundeck/api/domain/RundeckExecution.java | 24 +++++++++- .../org/rundeck/api/domain/RundeckNode.java | 3 +- .../api/domain/RundeckNodeIdentity.java | 14 ++++++ .../rundeck/api/parser/ExecutionParser.java | 26 ++++++++++ .../api/parser/ExecutionParserTest.java | 47 +++++++++++++++++++ .../api/parser/execution-result-v10.xml | 27 +++++++++++ 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/rundeck/api/domain/RundeckNodeIdentity.java create mode 100644 src/test/resources/org/rundeck/api/parser/execution-result-v10.xml diff --git a/src/main/java/org/rundeck/api/domain/RundeckExecution.java b/src/main/java/org/rundeck/api/domain/RundeckExecution.java index 0005554..20dc45c 100644 --- a/src/main/java/org/rundeck/api/domain/RundeckExecution.java +++ b/src/main/java/org/rundeck/api/domain/RundeckExecution.java @@ -17,6 +17,7 @@ package org.rundeck.api.domain; import java.io.Serializable; import java.util.Date; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.apache.commons.lang.time.DurationFormatUtils; @@ -52,6 +53,8 @@ public class RundeckExecution implements Serializable { private String description; private String argstring; private String project; + private Set successfulNodes; + private Set failedNodes; /** * @return the duration of the execution in milliseconds (or null if the duration is still running, or has been @@ -174,7 +177,10 @@ public class RundeckExecution implements Serializable { return "RundeckExecution [id=" + id + ", description=" + description + ", url=" + url + ", status=" + status + ", argstring=" + argstring + ", startedBy=" + startedBy + ", startedAt=" + startedAt + ", endedAt=" + endedAt - + ", durationInSeconds=" + getDurationInSeconds() + ", abortedBy=" + abortedBy + ", job=" + job + "]"; + + ", durationInSeconds=" + getDurationInSeconds() + ", abortedBy=" + abortedBy + ", job=" + job + + ", successfulNodes=" + getSuccessfulNodes() + + ", failedNodes=" + getFailedNodes() + + "]"; } @Override @@ -281,6 +287,22 @@ public class RundeckExecution implements Serializable { this.project = project; } + public Set getSuccessfulNodes() { + return successfulNodes; + } + + public void setSuccessfulNodes(Set successfulNodes) { + this.successfulNodes = successfulNodes; + } + + public Set getFailedNodes() { + return failedNodes; + } + + public void setFailedNodes(Set failedNodes) { + this.failedNodes = failedNodes; + } + /** * The status of an execution */ diff --git a/src/main/java/org/rundeck/api/domain/RundeckNode.java b/src/main/java/org/rundeck/api/domain/RundeckNode.java index 87a1a36..9d54b9f 100644 --- a/src/main/java/org/rundeck/api/domain/RundeckNode.java +++ b/src/main/java/org/rundeck/api/domain/RundeckNode.java @@ -23,7 +23,7 @@ import java.util.List; * * @author Vincent Behar */ -public class RundeckNode implements Serializable { +public class RundeckNode implements Serializable, RundeckNodeIdentity { private static final long serialVersionUID = 1L; @@ -63,6 +63,7 @@ public class RundeckNode implements Serializable { /** URL to an external resource model service. (optional) */ private String remoteUrl; + @Override public String getName() { return name; } diff --git a/src/main/java/org/rundeck/api/domain/RundeckNodeIdentity.java b/src/main/java/org/rundeck/api/domain/RundeckNodeIdentity.java new file mode 100644 index 0000000..063bfd3 --- /dev/null +++ b/src/main/java/org/rundeck/api/domain/RundeckNodeIdentity.java @@ -0,0 +1,14 @@ +package org.rundeck.api.domain; + + +/** + * Identifies a node by name + */ +public interface RundeckNodeIdentity { + /** + * Return the rundeck Node name + * + * @return + */ + String getName(); +} diff --git a/src/main/java/org/rundeck/api/parser/ExecutionParser.java b/src/main/java/org/rundeck/api/parser/ExecutionParser.java index 63ea0d1..90a6e8d 100644 --- a/src/main/java/org/rundeck/api/parser/ExecutionParser.java +++ b/src/main/java/org/rundeck/api/parser/ExecutionParser.java @@ -15,12 +15,18 @@ */ package org.rundeck.api.parser; +import java.util.Collections; import java.util.Date; +import java.util.HashSet; +import java.util.List; + import org.apache.commons.lang.StringUtils; import org.dom4j.Node; import org.rundeck.api.domain.RundeckExecution; import org.rundeck.api.domain.RundeckJob; import org.rundeck.api.domain.RundeckExecution.ExecutionStatus; +import org.rundeck.api.domain.RundeckNode; +import org.rundeck.api.domain.RundeckNodeIdentity; /** * Parser for a single {@link RundeckExecution} @@ -76,6 +82,26 @@ public class ExecutionParser implements XmlNodeParser { execution.setJob(job); } + final Node successfulNodes = execNode.selectSingleNode("successfulNodes"); + if (successfulNodes != null) { + final List rundeckNodes = + new ListParser(new NodeParser(), "successfulNodes/node") + .parseXmlNode(execNode); + execution.setSuccessfulNodes(new HashSet(rundeckNodes)); + }else{ + execution.setSuccessfulNodes(Collections.emptySet()); + } + + final Node failedNodes = execNode.selectSingleNode("failedNodes"); + if (failedNodes != null) { + final List rundeckNodes = + new ListParser(new NodeParser(), "failedNodes/node") + .parseXmlNode(execNode); + execution.setFailedNodes(new HashSet(rundeckNodes)); + } else { + execution.setFailedNodes(Collections.emptySet()); + } + return execution; } diff --git a/src/test/java/org/rundeck/api/parser/ExecutionParserTest.java b/src/test/java/org/rundeck/api/parser/ExecutionParserTest.java index 0e4daa4..b34cbb5 100644 --- a/src/test/java/org/rundeck/api/parser/ExecutionParserTest.java +++ b/src/test/java/org/rundeck/api/parser/ExecutionParserTest.java @@ -16,13 +16,17 @@ package org.rundeck.api.parser; import java.io.InputStream; +import java.util.Arrays; import java.util.Date; +import java.util.HashSet; + import org.dom4j.Document; import org.junit.Assert; import org.junit.Test; import org.rundeck.api.domain.RundeckExecution; import org.rundeck.api.domain.RundeckJob; import org.rundeck.api.domain.RundeckExecution.ExecutionStatus; +import org.rundeck.api.domain.RundeckNodeIdentity; /** * Test the {@link ExecutionParser} @@ -156,4 +160,47 @@ public class ExecutionParserTest { } + @Test + public void parseV10Execution() throws Exception { + InputStream input = getClass().getResourceAsStream("execution-result-v10.xml"); + Document document = ParserHelper.loadDocument(input); + + RundeckExecution execution = new ExecutionParser("result/executions/execution").parseXmlNode(document); + RundeckJob job = execution.getJob(); + + Assert.assertNotNull(job); + Assert.assertEquals(new Long(146), execution.getId()); + Assert.assertEquals("http://dignan.local:4440/execution/follow/146", execution.getUrl()); + Assert.assertEquals(ExecutionStatus.SUCCEEDED, execution.getStatus()); + Assert.assertEquals("admin", execution.getStartedBy()); + Assert.assertEquals(new Date(1389894502959L), execution.getStartedAt()); + Assert.assertEquals(new Date(1389894504561L), execution.getEndedAt()); + Assert.assertEquals((Long)(1389894504561L- 1389894502959L), execution.getDurationInMillis()); + Assert.assertEquals(null, execution.getAbortedBy()); + Assert.assertEquals("fdfd", execution.getProject()); + + Assert.assertNotNull(execution.getSuccessfulNodes()); + Assert.assertEquals(3, execution.getSuccessfulNodes().size()); + + HashSet expectedSuccess = new HashSet(); + expectedSuccess.addAll(Arrays.asList( + "node-111.qa.subgroup.mycompany.com", + "node-6.qa.subgroup.mycompany.com", + "node-14.qa.subgroup.mycompany.com")); + for (RundeckNodeIdentity rundeckNodeIdentity : execution.getSuccessfulNodes()) { + Assert.assertTrue(expectedSuccess.contains(rundeckNodeIdentity.getName())); + } + + Assert.assertNotNull(execution.getFailedNodes()); + Assert.assertEquals(3, execution.getFailedNodes().size()); + HashSet expectedFailure = new HashSet(); + expectedFailure.addAll(Arrays.asList( + "node-112.qa.subgroup.mycompany.com", + "node-62.qa.subgroup.mycompany.com", + "node-12.qa.subgroup.mycompany.com")); + for (RundeckNodeIdentity rundeckNodeIdentity : execution.getFailedNodes()) { + Assert.assertTrue(expectedFailure.contains(rundeckNodeIdentity.getName())); + } + } + } diff --git a/src/test/resources/org/rundeck/api/parser/execution-result-v10.xml b/src/test/resources/org/rundeck/api/parser/execution-result-v10.xml new file mode 100644 index 0000000..9c3db6d --- /dev/null +++ b/src/test/resources/org/rundeck/api/parser/execution-result-v10.xml @@ -0,0 +1,27 @@ + + + + admin + 2014-01-16T17:48:22Z + 2014-01-16T17:48:24Z + + test 1 + + fdfd + + + echo hi there + + + + + + + + + + + + + +