mirror of
https://github.com/Fishwaldo/rundeck-api-java-client.git
synced 2025-07-09 14:39:09 +00:00
add support for exporting jobs (to file)
This commit is contained in:
parent
64e0c346d3
commit
1594773a79
4 changed files with 131 additions and 33 deletions
5
pom.xml
5
pom.xml
|
@ -397,6 +397,11 @@
|
|||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.0.1</version>
|
||||
</dependency>
|
||||
<!-- XML Parsing -->
|
||||
<dependency>
|
||||
<groupId>dom4j</groupId>
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
*/
|
||||
package org.rundeck.api;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -117,6 +119,25 @@ class ApiCall {
|
|||
return execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath), parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the
|
||||
* API call.
|
||||
*
|
||||
* @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder}
|
||||
* @return a new {@link InputStream} instance, not linked with network resources
|
||||
* @throws RundeckApiException in case of error when calling the API
|
||||
* @throws RundeckApiLoginException if the login fails
|
||||
*/
|
||||
public InputStream get(ApiPathBuilder apiPath) throws RundeckApiException, RundeckApiLoginException {
|
||||
ByteArrayInputStream response = execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath));
|
||||
|
||||
// try to load the document, to throw an exception in case of error
|
||||
ParserHelper.loadDocument(response);
|
||||
response.reset();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -144,6 +165,23 @@ class ApiCall {
|
|||
*/
|
||||
private <T> T execute(HttpRequestBase request, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||
RundeckApiLoginException {
|
||||
// execute the request
|
||||
InputStream response = execute(request);
|
||||
|
||||
// read and parse the response
|
||||
Document xmlDocument = ParserHelper.loadDocument(response);
|
||||
return parser.parseXmlNode(xmlDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an HTTP request to the RunDeck instance. We will login first, and then execute the API call.
|
||||
*
|
||||
* @param request to execute. see {@link HttpGet}, {@link HttpDelete}, and so on...
|
||||
* @return a new {@link InputStream} instance, not linked with network resources
|
||||
* @throws RundeckApiException in case of error when calling the API
|
||||
* @throws RundeckApiLoginException if the login fails
|
||||
*/
|
||||
private ByteArrayInputStream execute(HttpRequestBase request) throws RundeckApiException, RundeckApiLoginException {
|
||||
HttpClient httpClient = instantiateHttpClient();
|
||||
try {
|
||||
login(httpClient);
|
||||
|
@ -176,6 +214,7 @@ class ApiCall {
|
|||
}
|
||||
}
|
||||
|
||||
// check the response code (should be 2xx, even in case of error : error message is in the XML result)
|
||||
if (response.getStatusLine().getStatusCode() / 100 != 2) {
|
||||
throw new RundeckApiException("Invalid HTTP response '" + response.getStatusLine() + "' for "
|
||||
+ request.getURI());
|
||||
|
@ -185,17 +224,12 @@ class ApiCall {
|
|||
+ response.getStatusLine());
|
||||
}
|
||||
|
||||
// read and parse the response
|
||||
Document xmlDocument = ParserHelper.loadDocument(response);
|
||||
T result = parser.parseXmlNode(xmlDocument);
|
||||
|
||||
// release the connection
|
||||
// return a new inputStream, so that we can close all network resources
|
||||
try {
|
||||
EntityUtils.consume(response.getEntity());
|
||||
return new ByteArrayInputStream(EntityUtils.toByteArray(response.getEntity()));
|
||||
} catch (IOException e) {
|
||||
throw new RundeckApiException("Failed to consume entity (release connection)", e);
|
||||
throw new RundeckApiException("Failed to consume entity and convert the inputStream", e);
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
httpClient.getConnectionManager().shutdown();
|
||||
}
|
||||
|
|
|
@ -15,11 +15,16 @@
|
|||
*/
|
||||
package org.rundeck.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.rundeck.api.RundeckApiException.RundeckApiLoginException;
|
||||
import org.rundeck.api.domain.RundeckAbort;
|
||||
|
@ -195,6 +200,85 @@ public class RundeckClient implements Serializable {
|
|||
new ListParser<RundeckJob>(new JobParser(), "result/jobs/job"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the definitions of all jobs that belongs to the given project, as an XML file
|
||||
*
|
||||
* @param filename path of the file where the content should be saved
|
||||
* @param project name of the project - mandatory
|
||||
* @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
|
||||
* @throws RundeckApiLoginException if the login failed
|
||||
* @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
|
||||
* @throws IOException if we failed to write to the file
|
||||
* @see #exportJobsToFile(String, String, String, String, String...)
|
||||
* @see #exportJobs(String)
|
||||
*/
|
||||
public void exportJobsToFile(String filename, String project) throws RundeckApiException, RundeckApiLoginException,
|
||||
IllegalArgumentException, IOException {
|
||||
exportJobsToFile(filename, project, null, null, new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the definitions of the jobs that belongs to the given project, and matches the given criteria (jobFilter,
|
||||
* groupPath and jobIds), as an XML file
|
||||
*
|
||||
* @param filename path of the file where the content should be saved
|
||||
* @param project name of the project - mandatory
|
||||
* @param jobFilter a filter for the job Name - optional
|
||||
* @param groupPath a group or partial group path to include all jobs within that group path - optional
|
||||
* @param jobIds a list of Job IDs to include - optional
|
||||
* @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
|
||||
* @throws RundeckApiLoginException if the login failed
|
||||
* @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
|
||||
* @throws IOException if we failed to write to the file
|
||||
* @see #exportJobsToFile(String, String)
|
||||
* @see #exportJobs(String, String, String, String...)
|
||||
*/
|
||||
public void exportJobsToFile(String filename, String project, String jobFilter, String groupPath, String... jobIds)
|
||||
throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException, IOException {
|
||||
InputStream inputStream = exportJobs(project, jobFilter, groupPath, jobIds);
|
||||
FileUtils.writeByteArrayToFile(new File(filename), IOUtils.toByteArray(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the definitions of all jobs that belongs to the given project
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @return an {@link InputStream} instance, not linked to any network resources - won't be null
|
||||
* @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
|
||||
* @throws RundeckApiLoginException if the login failed
|
||||
* @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
|
||||
* @see #exportJobs(String, String, String, String...)
|
||||
* @see #exportJobsToFile(String, String)
|
||||
*/
|
||||
public InputStream exportJobs(String project) throws RundeckApiException, RundeckApiLoginException,
|
||||
IllegalArgumentException {
|
||||
return exportJobs(project, null, null, new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the definitions of the jobs that belongs to the given project, and matches the given criteria (jobFilter,
|
||||
* groupPath and jobIds)
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @param jobFilter a filter for the job Name - optional
|
||||
* @param groupPath a group or partial group path to include all jobs within that group path - optional
|
||||
* @param jobIds a list of Job IDs to include - optional
|
||||
* @return an {@link InputStream} instance, not linked to any network resources - won't be null
|
||||
* @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
|
||||
* @throws RundeckApiLoginException if the login failed
|
||||
* @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
|
||||
* @see #exportJobs(String)
|
||||
* @see #exportJobsToFile(String, String, String, String, String...)
|
||||
*/
|
||||
public InputStream exportJobs(String project, String jobFilter, String groupPath, String... jobIds)
|
||||
throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
|
||||
AssertUtil.notBlank(project, "project is mandatory to export all jobs !");
|
||||
return new ApiCall(this).get(new ApiPathBuilder("/jobs/export").param("project", project)
|
||||
.param("jobFilter", jobFilter)
|
||||
.param("groupPath", groupPath)
|
||||
.param("idlist", StringUtils.join(jobIds, ",")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a job, identified by its project, group and name. Note that the groupPath is optional, as a job does not
|
||||
* need to belong to a group (either pass null, or an empty string).
|
||||
|
|
|
@ -15,9 +15,7 @@
|
|||
*/
|
||||
package org.rundeck.api.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Node;
|
||||
|
@ -31,35 +29,12 @@ import org.rundeck.api.RundeckApiException;
|
|||
*/
|
||||
public class ParserHelper {
|
||||
|
||||
/**
|
||||
* Load an XML {@link Document} from the given RunDeck {@link HttpResponse}.
|
||||
*
|
||||
* @param httpResponse from an API call to RunDeck
|
||||
* @return an XML {@link Document}
|
||||
* @throws RundeckApiException if we failed to read the response, or if the response is an error
|
||||
* @see #loadDocument(InputStream)
|
||||
*/
|
||||
public static Document loadDocument(HttpResponse httpResponse) throws RundeckApiException {
|
||||
InputStream inputStream = null;
|
||||
|
||||
try {
|
||||
inputStream = httpResponse.getEntity().getContent();
|
||||
} catch (IllegalStateException e) {
|
||||
throw new RundeckApiException("Failed to read RunDeck reponse", e);
|
||||
} catch (IOException e) {
|
||||
throw new RundeckApiException("Failed to read RunDeck reponse", e);
|
||||
}
|
||||
|
||||
return loadDocument(inputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an XML {@link Document} from the given {@link InputStream}
|
||||
*
|
||||
* @param inputStream from an API call to RunDeck
|
||||
* @return an XML {@link Document}
|
||||
* @throws RundeckApiException if we failed to read the response, or if the response is an error
|
||||
* @see #loadDocument(HttpResponse)
|
||||
*/
|
||||
public static Document loadDocument(InputStream inputStream) throws RundeckApiException {
|
||||
SAXReader reader = new SAXReader();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue