diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 4c24565..42acd0a 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -22,10 +22,12 @@ import java.util.Properties; import java.util.concurrent.TimeUnit; import org.apache.commons.lang.StringUtils; import org.rundeck.api.RundeckApiException.RundeckApiLoginException; +import org.rundeck.api.domain.RundeckAbort; import org.rundeck.api.domain.RundeckExecution; import org.rundeck.api.domain.RundeckJob; import org.rundeck.api.domain.RundeckProject; import org.rundeck.api.domain.RundeckExecution.ExecutionStatus; +import org.rundeck.api.parser.AbortParser; import org.rundeck.api.parser.ExecutionParser; import org.rundeck.api.parser.ExecutionsParser; import org.rundeck.api.parser.JobParser; @@ -655,6 +657,22 @@ public class RundeckClient implements Serializable { new ExecutionParser("result/executions/execution")); } + /** + * Abort an execution (identified by the given ID). The execution should be running... + * + * @param executionId identifier of the execution - mandatory + * @return a {@link RundeckAbort} instance - won't be null + * @throws RundeckApiException in case of error when calling the API (non-existent execution with this ID) + * @throws RundeckApiLoginException if the login failed + * @throws IllegalArgumentException if the executionId is null + */ + public RundeckAbort abortExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException, + IllegalArgumentException { + AssertUtil.notNull(executionId, "executionId is mandatory to abort an execution !"); + return new ApiCall(this).get(new ApiPathBuilder("/execution/", executionId.toString(), "/abort"), + new AbortParser("result/abort")); + } + public String getUrl() { return url; } diff --git a/src/main/java/org/rundeck/api/domain/RundeckAbort.java b/src/main/java/org/rundeck/api/domain/RundeckAbort.java new file mode 100644 index 0000000..d0b70cb --- /dev/null +++ b/src/main/java/org/rundeck/api/domain/RundeckAbort.java @@ -0,0 +1,92 @@ +/* + * Copyright 2011 Vincent Behar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.rundeck.api.domain; + +import java.io.Serializable; + +/** + * Represents an abort of a {@link RundeckExecution} + * + * @author Vincent Behar + */ +public class RundeckAbort implements Serializable { + + private static final long serialVersionUID = 1L; + + private AbortStatus status; + + private RundeckExecution execution; + + public AbortStatus getStatus() { + return status; + } + + public void setStatus(AbortStatus status) { + this.status = status; + } + + public RundeckExecution getExecution() { + return execution; + } + + public void setExecution(RundeckExecution execution) { + this.execution = execution; + } + + @Override + public String toString() { + return "RundeckAbort [status=" + status + ", execution=" + execution + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((execution == null) ? 0 : execution.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RundeckAbort other = (RundeckAbort) obj; + if (execution == null) { + if (other.execution != null) + return false; + } else if (!execution.equals(other.execution)) + return false; + if (status == null) { + if (other.status != null) + return false; + } else if (!status.equals(other.status)) + return false; + return true; + } + + /** + * The status of an abort + */ + public static enum AbortStatus { + PENDING, FAILED, ABORTED; + } + +} diff --git a/src/main/java/org/rundeck/api/parser/AbortParser.java b/src/main/java/org/rundeck/api/parser/AbortParser.java new file mode 100644 index 0000000..87f69f7 --- /dev/null +++ b/src/main/java/org/rundeck/api/parser/AbortParser.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011 Vincent Behar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.rundeck.api.parser; + +import org.apache.commons.lang.StringUtils; +import org.dom4j.Node; +import org.rundeck.api.domain.RundeckAbort; +import org.rundeck.api.domain.RundeckExecution; +import org.rundeck.api.domain.RundeckAbort.AbortStatus; + +/** + * Parser for a single {@link RundeckAbort} + * + * @author Vincent Behar + */ +public class AbortParser implements NodeParser { + + private String xpath; + + public AbortParser() { + super(); + } + + /** + * @param xpath of the abort element if it is not the root node + */ + public AbortParser(String xpath) { + super(); + this.xpath = xpath; + } + + @Override + public RundeckAbort parseNode(Node node) { + Node abortNode = xpath != null ? node.selectSingleNode(xpath) : node; + + RundeckAbort abort = new RundeckAbort(); + + try { + abort.setStatus(AbortStatus.valueOf(StringUtils.upperCase(abortNode.valueOf("@status")))); + } catch (IllegalArgumentException e) { + } + + Node execNode = abortNode.selectSingleNode("execution"); + if (execNode != null) { + RundeckExecution execution = new ExecutionParser().parseNode(execNode); + abort.setExecution(execution); + } + + return abort; + } + +} diff --git a/src/test/java/org/rundeck/api/parser/AbortParserTest.java b/src/test/java/org/rundeck/api/parser/AbortParserTest.java new file mode 100644 index 0000000..22f64b7 --- /dev/null +++ b/src/test/java/org/rundeck/api/parser/AbortParserTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2011 Vincent Behar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.rundeck.api.parser; + +import java.io.InputStream; +import org.dom4j.Document; +import org.junit.Assert; +import org.junit.Test; +import org.rundeck.api.domain.RundeckAbort; +import org.rundeck.api.domain.RundeckExecution; +import org.rundeck.api.domain.RundeckAbort.AbortStatus; +import org.rundeck.api.domain.RundeckExecution.ExecutionStatus; + +/** + * Test the {@link AbortParser} + * + * @author Vincent Behar + */ +public class AbortParserTest { + + @Test + public void parsePendingNode() throws Exception { + InputStream input = getClass().getResourceAsStream("abort-pending.xml"); + Document document = ParserHelper.loadDocument(input); + + RundeckAbort abort = new AbortParser("result/abort").parseNode(document); + RundeckExecution execution = abort.getExecution(); + + Assert.assertEquals(AbortStatus.PENDING, abort.getStatus()); + + Assert.assertEquals(new Long(1), execution.getId()); + Assert.assertEquals(ExecutionStatus.RUNNING, execution.getStatus()); + } + + @Test + public void parseFailedNode() throws Exception { + InputStream input = getClass().getResourceAsStream("abort-failed.xml"); + Document document = ParserHelper.loadDocument(input); + + RundeckAbort abort = new AbortParser("result/abort").parseNode(document); + RundeckExecution execution = abort.getExecution(); + + Assert.assertEquals(AbortStatus.FAILED, abort.getStatus()); + + Assert.assertEquals(new Long(1), execution.getId()); + Assert.assertEquals(ExecutionStatus.SUCCEEDED, execution.getStatus()); + } + +} diff --git a/src/test/resources/org/rundeck/api/parser/abort-failed.xml b/src/test/resources/org/rundeck/api/parser/abort-failed.xml new file mode 100644 index 0000000..8292e65 --- /dev/null +++ b/src/test/resources/org/rundeck/api/parser/abort-failed.xml @@ -0,0 +1 @@ +Execution status: previously succeeded \ No newline at end of file diff --git a/src/test/resources/org/rundeck/api/parser/abort-pending.xml b/src/test/resources/org/rundeck/api/parser/abort-pending.xml new file mode 100644 index 0000000..05d9098 --- /dev/null +++ b/src/test/resources/org/rundeck/api/parser/abort-pending.xml @@ -0,0 +1 @@ +Execution status: running \ No newline at end of file