mirror of
https://github.com/Fishwaldo/rundeck-api-java-client.git
synced 2025-07-07 21:48:30 +00:00
Add bulk Delete executions endpoint
This commit is contained in:
parent
bbe599b915
commit
a7c0c22699
8 changed files with 361 additions and 1 deletions
|
@ -23,6 +23,7 @@ import org.rundeck.api.RundeckApiException.RundeckApiLoginException;
|
|||
import org.rundeck.api.RundeckApiException.RundeckApiTokenException;
|
||||
import org.rundeck.api.domain.*;
|
||||
import org.rundeck.api.domain.RundeckExecution.ExecutionStatus;
|
||||
import org.rundeck.api.generator.DeleteExecutionsGenerator;
|
||||
import org.rundeck.api.generator.ProjectConfigGenerator;
|
||||
import org.rundeck.api.generator.ProjectConfigPropertyGenerator;
|
||||
import org.rundeck.api.generator.ProjectGenerator;
|
||||
|
@ -95,6 +96,7 @@ public class RundeckClient implements Serializable {
|
|||
V9(9),
|
||||
V10(10),
|
||||
V11(11),
|
||||
V12(12),
|
||||
;
|
||||
|
||||
private int versionNumber;
|
||||
|
@ -108,7 +110,7 @@ public class RundeckClient implements Serializable {
|
|||
}
|
||||
}
|
||||
/** Version of the API supported */
|
||||
public static final transient int API_VERSION = Version.V11.getVersionNumber();
|
||||
public static final transient int API_VERSION = Version.V12.getVersionNumber();
|
||||
|
||||
private static final String API = "/api/";
|
||||
|
||||
|
@ -1643,6 +1645,30 @@ public class RundeckClient implements Serializable {
|
|||
return new ApiCall(this).get(apiPath, new AbortParser(rootXpath()+"/abort"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a set of executions, identified by the given IDs
|
||||
*
|
||||
* @param executionIds set of identifiers for the executions - mandatory
|
||||
* @return a {@link RundeckExecution} 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 fails (in case of login-based authentication)
|
||||
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||
* @throws IllegalArgumentException if the executionId is null
|
||||
*/
|
||||
public DeleteExecutionsResponse deleteExecutions(Set<Long> executionIds)
|
||||
throws RundeckApiException, RundeckApiLoginException,
|
||||
RundeckApiTokenException, IllegalArgumentException
|
||||
{
|
||||
AssertUtil.notNull(executionIds, "executionIds is mandatory to abort an execution !");
|
||||
final ApiPathBuilder apiPath = new ApiPathBuilder("/executions/delete").xml(
|
||||
new DeleteExecutionsGenerator(executionIds)
|
||||
);
|
||||
return new ApiCall(this).post(
|
||||
apiPath,
|
||||
new DeleteExecutionsResponseParser( rootXpath() + "/deleteExecutions")
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* History
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package org.rundeck.api.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DeleteExecutionsResponse is ...
|
||||
*
|
||||
* @author Greg Schueler <greg@simplifyops.com>
|
||||
* @since 2014-11-06
|
||||
*/
|
||||
public class DeleteExecutionsResponse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int failedCount;
|
||||
private int successCount;
|
||||
private boolean allsuccessful;
|
||||
private int requestCount;
|
||||
private List<DeleteFailure> failures;
|
||||
|
||||
public int getFailedCount() {
|
||||
return failedCount;
|
||||
}
|
||||
|
||||
public void setFailedCount(final int failedCount) {
|
||||
this.failedCount = failedCount;
|
||||
}
|
||||
|
||||
public int getSuccessCount() {
|
||||
return successCount;
|
||||
}
|
||||
|
||||
public void setSuccessCount(final int successCount) {
|
||||
this.successCount = successCount;
|
||||
}
|
||||
|
||||
public boolean isAllsuccessful() {
|
||||
return allsuccessful;
|
||||
}
|
||||
|
||||
public void setAllsuccessful(final boolean allsuccessful) {
|
||||
this.allsuccessful = allsuccessful;
|
||||
}
|
||||
|
||||
public int getRequestCount() {
|
||||
return requestCount;
|
||||
}
|
||||
|
||||
public void setRequestCount(final int requestCount) {
|
||||
this.requestCount = requestCount;
|
||||
}
|
||||
|
||||
public List<DeleteFailure> getFailures() {
|
||||
return failures;
|
||||
}
|
||||
|
||||
public void setFailures(final List<DeleteFailure> failures) {
|
||||
this.failures = failures;
|
||||
}
|
||||
|
||||
public static class DeleteFailure implements Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Long executionId;
|
||||
private String message;
|
||||
|
||||
public Long getExecutionId() {
|
||||
return executionId;
|
||||
}
|
||||
|
||||
public void setExecutionId(final Long executionId) {
|
||||
this.executionId = executionId;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(final String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.rundeck.api.generator;
|
||||
|
||||
import org.dom4j.DocumentFactory;
|
||||
import org.dom4j.Element;
|
||||
import org.rundeck.api.domain.ProjectConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* DeleteExecutionsGenerator is ...
|
||||
*
|
||||
* @author Greg Schueler <greg@simplifyops.com>
|
||||
* @since 2014-11-06
|
||||
*/
|
||||
public class DeleteExecutionsGenerator extends BaseDocGenerator {
|
||||
private Set<Long> executionIds;
|
||||
|
||||
public DeleteExecutionsGenerator(final Set<Long> executionIds) {
|
||||
this.executionIds = executionIds;
|
||||
}
|
||||
|
||||
@Override public Element generateXmlElement() {
|
||||
Element rootElem = DocumentFactory.getInstance().createElement("executions");
|
||||
for (Long executionId : executionIds) {
|
||||
rootElem.addElement("execution").addAttribute("id", Long.toString(executionId));
|
||||
}
|
||||
return rootElem;
|
||||
}
|
||||
|
||||
public Set<Long> getExecutionIds() {
|
||||
return executionIds;
|
||||
}
|
||||
|
||||
public void setExecutionIds(final Set<Long> executionIds) {
|
||||
this.executionIds = executionIds;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.rundeck.api.parser;
|
||||
|
||||
import org.dom4j.Node;
|
||||
import org.rundeck.api.domain.DeleteExecutionsResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DeleteExecutionsResponseParser is ...
|
||||
*
|
||||
* @author Greg Schueler <greg@simplifyops.com>
|
||||
* @since 2014-11-06
|
||||
*/
|
||||
public class DeleteExecutionsResponseParser implements XmlNodeParser<DeleteExecutionsResponse> {
|
||||
private String xpath;
|
||||
|
||||
public DeleteExecutionsResponseParser(final String xpath) {
|
||||
this.xpath = xpath;
|
||||
}
|
||||
|
||||
@Override public DeleteExecutionsResponse parseXmlNode(final Node node) {
|
||||
final Node baseNode = xpath != null ? node.selectSingleNode(xpath) : node;
|
||||
|
||||
final DeleteExecutionsResponse response = new DeleteExecutionsResponse();
|
||||
response.setAllsuccessful(Boolean.parseBoolean(baseNode.valueOf("@allsuccessful")));
|
||||
response.setRequestCount(Integer.parseInt(baseNode.valueOf("@requestCount")));
|
||||
response.setSuccessCount(Integer.parseInt(baseNode.valueOf("successful/@count")));
|
||||
|
||||
final Node failedNode = baseNode.selectSingleNode("failed");
|
||||
//parse failures
|
||||
final List<DeleteExecutionsResponse.DeleteFailure> failures = new ArrayList
|
||||
<DeleteExecutionsResponse.DeleteFailure>();
|
||||
int failedCount = 0;
|
||||
if (null != failedNode) {
|
||||
failedCount = Integer.parseInt(baseNode.valueOf("failed/@count"));
|
||||
final List list = baseNode.selectNodes("failed/execution");
|
||||
|
||||
for (final Object o : list) {
|
||||
final Node execNode = (Node) o;
|
||||
final DeleteExecutionsResponse.DeleteFailure deleteFailure =
|
||||
new DeleteExecutionsResponse.DeleteFailure();
|
||||
deleteFailure.setExecutionId(Long.parseLong(execNode.valueOf("@id")));
|
||||
deleteFailure.setMessage(execNode.valueOf("@message"));
|
||||
failures.add(deleteFailure);
|
||||
}
|
||||
}
|
||||
response.setFailedCount(failedCount);
|
||||
response.setFailures(failures);
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ public class RundeckClientTest {
|
|||
public static final String TEST_TOKEN_5 = "C3O6d5O98Kr6Dpv71sdE4ERdCuU12P6d";
|
||||
public static final String TEST_TOKEN_6 = "Do4d3NUD5DKk21DR4sNK755RcPk618vn";
|
||||
public static final String TEST_TOKEN_7 = "8Dp9op111ER6opsDRkddvE86K9sE499s";
|
||||
public static final String TEST_TOKEN_8 = "GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI";
|
||||
|
||||
@Rule
|
||||
public Recorder recorder = new Recorder();
|
||||
|
@ -1490,6 +1491,87 @@ public class RundeckClientTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* delete executions with failure
|
||||
*/
|
||||
@Test
|
||||
@Betamax(tape = "delete_executions_unauthorized", mode = TapeMode.READ_ONLY)
|
||||
public void deleteExecutionsUnauthorized() throws Exception {
|
||||
final RundeckClient client = createClient(TEST_TOKEN_8, 12);
|
||||
final DeleteExecutionsResponse response = client.deleteExecutions(
|
||||
new HashSet<Long>() {{
|
||||
add(640L);
|
||||
add(641L);
|
||||
}}
|
||||
);
|
||||
Assert.assertEquals(2, response.getRequestCount());
|
||||
Assert.assertEquals(0, response.getSuccessCount());
|
||||
Assert.assertEquals(2, response.getFailedCount());
|
||||
Assert.assertFalse(response.isAllsuccessful());
|
||||
Assert.assertNotNull(response.getFailures());
|
||||
Assert.assertEquals(2, response.getFailures().size());
|
||||
Assert.assertEquals(Long.valueOf(641L), response.getFailures().get(0).getExecutionId());
|
||||
Assert.assertEquals(
|
||||
"Unauthorized: Delete execution in project test",
|
||||
response.getFailures().get(0).getMessage()
|
||||
);
|
||||
Assert.assertEquals(Long.valueOf(640L), response.getFailures().get(1).getExecutionId());
|
||||
Assert.assertEquals(
|
||||
"Unauthorized: Delete execution in project test",
|
||||
response.getFailures().get(1).getMessage()
|
||||
);
|
||||
}
|
||||
/**
|
||||
* delete executions with success
|
||||
*/
|
||||
@Test
|
||||
@Betamax(tape = "delete_executions_success", mode = TapeMode.READ_ONLY)
|
||||
public void deleteExecutionsSuccess() throws Exception {
|
||||
final RundeckClient client = createClient(TEST_TOKEN_8, 12);
|
||||
final DeleteExecutionsResponse response = client.deleteExecutions(
|
||||
new HashSet<Long>() {{
|
||||
add(640L);
|
||||
add(641L);
|
||||
}}
|
||||
);
|
||||
Assert.assertEquals(2, response.getRequestCount());
|
||||
Assert.assertEquals(2, response.getSuccessCount());
|
||||
Assert.assertEquals(0, response.getFailedCount());
|
||||
Assert.assertTrue(response.isAllsuccessful());
|
||||
Assert.assertNotNull(response.getFailures());
|
||||
Assert.assertEquals(0, response.getFailures().size());
|
||||
}
|
||||
/**
|
||||
* delete executions mixed success
|
||||
*/
|
||||
@Test
|
||||
@Betamax(tape = "delete_executions_mixed", mode = TapeMode.READ_ONLY)
|
||||
public void deleteExecutionsMixed() throws Exception {
|
||||
final RundeckClient client = createClient(TEST_TOKEN_8, 12);
|
||||
final DeleteExecutionsResponse response = client.deleteExecutions(
|
||||
new HashSet<Long>() {{
|
||||
add(642L);
|
||||
add(640L);
|
||||
add(1640L);
|
||||
}}
|
||||
);
|
||||
Assert.assertEquals(3, response.getRequestCount());
|
||||
Assert.assertEquals(1, response.getSuccessCount());
|
||||
Assert.assertEquals(2, response.getFailedCount());
|
||||
Assert.assertFalse(response.isAllsuccessful());
|
||||
Assert.assertNotNull(response.getFailures());
|
||||
Assert.assertEquals(2, response.getFailures().size());
|
||||
Assert.assertEquals(Long.valueOf(1640L), response.getFailures().get(0).getExecutionId());
|
||||
Assert.assertEquals(
|
||||
"Execution Not found: 1640",
|
||||
response.getFailures().get(0).getMessage()
|
||||
);
|
||||
Assert.assertEquals(Long.valueOf(640L), response.getFailures().get(1).getExecutionId());
|
||||
Assert.assertEquals(
|
||||
"Execution Not found: 640",
|
||||
response.getFailures().get(1).getMessage()
|
||||
);
|
||||
}
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// not that you can put whatever here, because we don't actually connect to the RunDeck instance
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
!tape
|
||||
name: delete_executions_mixed
|
||||
interactions:
|
||||
- recorded: 2014-11-06T17:29:44.266Z
|
||||
request:
|
||||
method: POST
|
||||
uri: http://rundeck.local:4440/api/12/executions/delete
|
||||
headers:
|
||||
Accept: text/xml
|
||||
Content-Type: application/xml
|
||||
Host: rundeck.local:4440
|
||||
Proxy-Connection: Keep-Alive
|
||||
Transfer-Encoding: chunked
|
||||
User-Agent: RunDeck API Java Client 12
|
||||
X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
Content-Type: application/xml;charset=UTF-8
|
||||
Expires: Thu, 01 Jan 1970 00:00:00 GMT
|
||||
Server: Jetty(7.6.0.v20120127)
|
||||
Set-Cookie: JSESSIONID=smlj6wcfe4yccemt6bptnmgy;Path=/
|
||||
X-Rundeck-API-Version: '12'
|
||||
X-Rundeck-API-XML-Response-Wrapper: 'false'
|
||||
body: !!binary |-
|
||||
PGRlbGV0ZUV4ZWN1dGlvbnMgcmVxdWVzdENvdW50PSczJyBhbGxzdWNjZXNzZnVsPSdmYWxzZSc+CiAgPHN1Y2Nlc3NmdWwgY291bnQ9JzEnIC8+CiAgPGZhaWxlZCBjb3VudD0nMic+CiAgICA8ZXhlY3V0aW9uIGlkPScxNjQwJyBtZXNzYWdlPSdFeGVjdXRpb24gTm90IGZvdW5kOiAxNjQwJyAvPgogICAgPGV4ZWN1dGlvbiBpZD0nNjQwJyBtZXNzYWdlPSdFeGVjdXRpb24gTm90IGZvdW5kOiA2NDAnIC8+CiAgPC9mYWlsZWQ+CjwvZGVsZXRlRXhlY3V0aW9ucz4=
|
|
@ -0,0 +1,26 @@
|
|||
!tape
|
||||
name: delete_executions_success
|
||||
interactions:
|
||||
- recorded: 2014-11-06T17:24:56.487Z
|
||||
request:
|
||||
method: POST
|
||||
uri: http://rundeck.local:4440/api/12/executions/delete
|
||||
headers:
|
||||
Accept: text/xml
|
||||
Content-Type: application/xml
|
||||
Host: rundeck.local:4440
|
||||
Proxy-Connection: Keep-Alive
|
||||
Transfer-Encoding: chunked
|
||||
User-Agent: RunDeck API Java Client 12
|
||||
X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
Content-Type: application/xml;charset=UTF-8
|
||||
Expires: Thu, 01 Jan 1970 00:00:00 GMT
|
||||
Server: Jetty(7.6.0.v20120127)
|
||||
Set-Cookie: JSESSIONID=1xueq6cjfrsnxjn43hcfadqyk;Path=/
|
||||
X-Rundeck-API-Version: '12'
|
||||
X-Rundeck-API-XML-Response-Wrapper: 'false'
|
||||
body: !!binary |-
|
||||
PGRlbGV0ZUV4ZWN1dGlvbnMgcmVxdWVzdENvdW50PScyJyBhbGxzdWNjZXNzZnVsPSd0cnVlJz4KICA8c3VjY2Vzc2Z1bCBjb3VudD0nMicgLz4KPC9kZWxldGVFeGVjdXRpb25zPg==
|
|
@ -0,0 +1,26 @@
|
|||
!tape
|
||||
name: delete_executions_success
|
||||
interactions:
|
||||
- recorded: 2014-11-06T17:15:24.673Z
|
||||
request:
|
||||
method: POST
|
||||
uri: http://rundeck.local:4440/api/12/executions/delete
|
||||
headers:
|
||||
Accept: text/xml
|
||||
Content-Type: application/xml
|
||||
Host: rundeck.local:4440
|
||||
Proxy-Connection: Keep-Alive
|
||||
Transfer-Encoding: chunked
|
||||
User-Agent: RunDeck API Java Client 12
|
||||
X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
Content-Type: application/xml;charset=UTF-8
|
||||
Expires: Thu, 01 Jan 1970 00:00:00 GMT
|
||||
Server: Jetty(7.6.0.v20120127)
|
||||
Set-Cookie: JSESSIONID=1kzmot0r2scpjfxlcpfthh7tz;Path=/
|
||||
X-Rundeck-API-Version: '12'
|
||||
X-Rundeck-API-XML-Response-Wrapper: 'false'
|
||||
body: !!binary |-
|
||||
PGRlbGV0ZUV4ZWN1dGlvbnMgcmVxdWVzdENvdW50PScyJyBhbGxzdWNjZXNzZnVsPSdmYWxzZSc+CiAgPHN1Y2Nlc3NmdWwgY291bnQ9JzAnIC8+CiAgPGZhaWxlZCBjb3VudD0nMic+CiAgICA8ZXhlY3V0aW9uIGlkPSc2NDEnIG1lc3NhZ2U9J1VuYXV0aG9yaXplZDogRGVsZXRlIGV4ZWN1dGlvbiBpbiBwcm9qZWN0IHRlc3QnIC8+CiAgICA8ZXhlY3V0aW9uIGlkPSc2NDAnIG1lc3NhZ2U9J1VuYXV0aG9yaXplZDogRGVsZXRlIGV4ZWN1dGlvbiBpbiBwcm9qZWN0IHRlc3QnIC8+CiAgPC9mYWlsZWQ+CjwvZGVsZXRlRXhlY3V0aW9ucz4=
|
Loading…
Add table
Add a link
Reference in a new issue