mirror of
https://github.com/Fishwaldo/rundeck-api-java-client.git
synced 2025-07-07 13:38:23 +00:00
add support for deleting a job
This commit is contained in:
parent
01cd512b0b
commit
64e0c346d3
5 changed files with 166 additions and 8 deletions
|
@ -30,8 +30,10 @@ import org.apache.http.NameValuePair;
|
|||
import org.apache.http.ParseException;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.conn.ssl.TrustStrategy;
|
||||
|
@ -41,8 +43,8 @@ import org.apache.http.protocol.HTTP;
|
|||
import org.apache.http.util.EntityUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.rundeck.api.RundeckApiException.RundeckApiLoginException;
|
||||
import org.rundeck.api.parser.XmlNodeParser;
|
||||
import org.rundeck.api.parser.ParserHelper;
|
||||
import org.rundeck.api.parser.XmlNodeParser;
|
||||
import org.rundeck.api.util.AssertUtil;
|
||||
|
||||
/**
|
||||
|
@ -110,9 +112,38 @@ class ApiCall {
|
|||
* @throws RundeckApiException in case of error when calling the API
|
||||
* @throws RundeckApiLoginException if the login fails
|
||||
*/
|
||||
public <T> T get(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException, RundeckApiLoginException {
|
||||
String apiUrl = client.getUrl() + RundeckClient.API_ENDPOINT + apiPath;
|
||||
public <T> T get(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||
RundeckApiLoginException {
|
||||
return execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath), parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an HTTP DELETE request to the RunDeck instance, on the given path. We will login first, and then execute
|
||||
* the API call. At the end, the given parser will be used to convert the response to a more useful result object.
|
||||
*
|
||||
* @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder}
|
||||
* @param parser used to parse the response
|
||||
* @return the result of the call, as formatted by the parser
|
||||
* @throws RundeckApiException in case of error when calling the API
|
||||
* @throws RundeckApiLoginException if the login fails
|
||||
*/
|
||||
public <T> T delete(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||
RundeckApiLoginException {
|
||||
return execute(new HttpDelete(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath), parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an HTTP request to the RunDeck instance. We will login first, and then execute the API call. At the end,
|
||||
* the given parser will be used to convert the response to a more useful result object.
|
||||
*
|
||||
* @param request to execute. see {@link HttpGet}, {@link HttpDelete}, and so on...
|
||||
* @param parser used to parse the response
|
||||
* @return the result of the call, as formatted by the parser
|
||||
* @throws RundeckApiException in case of error when calling the API
|
||||
* @throws RundeckApiLoginException if the login fails
|
||||
*/
|
||||
private <T> T execute(HttpRequestBase request, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||
RundeckApiLoginException {
|
||||
HttpClient httpClient = instantiateHttpClient();
|
||||
try {
|
||||
login(httpClient);
|
||||
|
@ -120,12 +151,34 @@ class ApiCall {
|
|||
// execute the HTTP request
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = httpClient.execute(new HttpGet(apiUrl));
|
||||
response = httpClient.execute(request);
|
||||
} catch (IOException e) {
|
||||
throw new RundeckApiException("Failed to execute an HTTP GET on url : " + apiUrl, e);
|
||||
throw new RundeckApiException("Failed to execute an HTTP " + request.getMethod() + " on url : "
|
||||
+ request.getURI(), e);
|
||||
}
|
||||
|
||||
// HTTP client refuses to handle redirects (code 3xx) for DELETE, so we have to do it manually...
|
||||
// See http://rundeck.lighthouseapp.com/projects/59277/tickets/248
|
||||
if (response.getStatusLine().getStatusCode() / 100 == 3
|
||||
&& HttpDelete.METHOD_NAME.equals(request.getMethod())) {
|
||||
String newLocation = response.getFirstHeader("Location").getValue();
|
||||
try {
|
||||
EntityUtils.consume(response.getEntity());
|
||||
} catch (IOException e) {
|
||||
throw new RundeckApiException("Failed to consume entity (release connection)", e);
|
||||
}
|
||||
request = new HttpDelete(newLocation);
|
||||
try {
|
||||
response = httpClient.execute(request);
|
||||
} catch (IOException e) {
|
||||
throw new RundeckApiException("Failed to execute an HTTP " + request.getMethod() + " on url : "
|
||||
+ request.getURI(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.getStatusLine().getStatusCode() / 100 != 2) {
|
||||
throw new RundeckApiException("Invalid HTTP response '" + response.getStatusLine() + "' for " + apiUrl);
|
||||
throw new RundeckApiException("Invalid HTTP response '" + response.getStatusLine() + "' for "
|
||||
+ request.getURI());
|
||||
}
|
||||
if (response.getEntity() == null) {
|
||||
throw new RundeckApiException("Empty RunDeck response ! HTTP status line is : "
|
||||
|
@ -235,5 +288,4 @@ class ApiCall {
|
|||
httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, socketFactory));
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,16 +24,17 @@ 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.RundeckExecution.ExecutionStatus;
|
||||
import org.rundeck.api.domain.RundeckJob;
|
||||
import org.rundeck.api.domain.RundeckNode;
|
||||
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.JobParser;
|
||||
import org.rundeck.api.parser.ListParser;
|
||||
import org.rundeck.api.parser.NodeParser;
|
||||
import org.rundeck.api.parser.ProjectParser;
|
||||
import org.rundeck.api.parser.StringParser;
|
||||
import org.rundeck.api.util.AssertUtil;
|
||||
import org.rundeck.api.util.ParametersUtil;
|
||||
|
||||
|
@ -229,6 +230,21 @@ public class RundeckClient implements Serializable {
|
|||
return new ApiCall(this).get(new ApiPathBuilder("/job/", jobId), new JobParser("joblist/job"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single job, identified by the given ID
|
||||
*
|
||||
* @param jobId identifier of the job - mandatory
|
||||
* @return the success message (note that in case of error, you'll get an exception)
|
||||
* @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
|
||||
* @throws RundeckApiLoginException if the login failed
|
||||
* @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
|
||||
*/
|
||||
public String deleteJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
|
||||
IllegalArgumentException {
|
||||
AssertUtil.notBlank(jobId, "jobId is mandatory to delete a job !");
|
||||
return new ApiCall(this).delete(new ApiPathBuilder("/job/", jobId), new StringParser("result/success/message"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
|
||||
* end of the job execution)
|
||||
|
|
49
src/main/java/org/rundeck/api/parser/StringParser.java
Normal file
49
src/main/java/org/rundeck/api/parser/StringParser.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Parser for a single {@link String}
|
||||
*
|
||||
* @author Vincent Behar
|
||||
*/
|
||||
public class StringParser implements XmlNodeParser<String> {
|
||||
|
||||
private String xpath;
|
||||
|
||||
public StringParser() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param xpath of the string element if it is not the root node
|
||||
*/
|
||||
public StringParser(String xpath) {
|
||||
super();
|
||||
this.xpath = xpath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseXmlNode(Node node) {
|
||||
Node strNode = xpath != null ? node.selectSingleNode(xpath) : node;
|
||||
|
||||
return StringUtils.trimToNull(strNode.getStringValue());
|
||||
}
|
||||
|
||||
}
|
40
src/test/java/org/rundeck/api/parser/StringParserTest.java
Normal file
40
src/test/java/org/rundeck/api/parser/StringParserTest.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Test the {@link StringParser}
|
||||
*
|
||||
* @author Vincent Behar
|
||||
*/
|
||||
public class StringParserTest {
|
||||
|
||||
@Test
|
||||
public void parseJob() throws Exception {
|
||||
InputStream input = getClass().getResourceAsStream("message.xml");
|
||||
Document document = ParserHelper.loadDocument(input);
|
||||
|
||||
String message = new StringParser("result/success/message").parseXmlNode(document);
|
||||
|
||||
Assert.assertEquals("Job was successfully deleted: [1] /job-name", message);
|
||||
}
|
||||
|
||||
}
|
1
src/test/resources/org/rundeck/api/parser/message.xml
Normal file
1
src/test/resources/org/rundeck/api/parser/message.xml
Normal file
|
@ -0,0 +1 @@
|
|||
<result success='true' apiversion="1"><success><message>Job was successfully deleted: [1] /job-name</message></success></result>
|
Loading…
Add table
Add a link
Reference in a new issue