mirror of
https://github.com/Fishwaldo/rundeck-api-java-client.git
synced 2025-07-08 05:58:39 +00:00
start working on a new-style api (fluent api / method chaining)
This commit is contained in:
parent
d28b7d7064
commit
564a3ce90f
13 changed files with 1208 additions and 92 deletions
|
@ -66,6 +66,7 @@ import org.rundeck.api.util.AssertUtil;
|
||||||
*
|
*
|
||||||
* @author Vincent Behar
|
* @author Vincent Behar
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
class ApiCall {
|
class ApiCall {
|
||||||
|
|
||||||
/** RunDeck HTTP header for the auth-token (in case of token-based authentication) */
|
/** RunDeck HTTP header for the auth-token (in case of token-based authentication) */
|
||||||
|
@ -158,14 +159,14 @@ class ApiCall {
|
||||||
* Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the
|
* Execute an HTTP GET 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.
|
* 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 apiPath on which we will make the HTTP request - see {@link OldApiPathBuilder}
|
||||||
* @param parser used to parse the response
|
* @param parser used to parse the response
|
||||||
* @return the result of the call, as formatted by the parser
|
* @return the result of the call, as formatted by the parser
|
||||||
* @throws RundeckApiException in case of error when calling the API
|
* @throws RundeckApiException in case of error when calling the API
|
||||||
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
|
* @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 RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
*/
|
*/
|
||||||
public <T> T get(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
public <T> T get(OldApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||||
RundeckApiLoginException, RundeckApiTokenException {
|
RundeckApiLoginException, RundeckApiTokenException {
|
||||||
return execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath), parser);
|
return execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath), parser);
|
||||||
}
|
}
|
||||||
|
@ -174,13 +175,13 @@ class ApiCall {
|
||||||
* Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the
|
* Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the
|
||||||
* API call.
|
* API call.
|
||||||
*
|
*
|
||||||
* @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder}
|
* @param apiPath on which we will make the HTTP request - see {@link OldApiPathBuilder}
|
||||||
* @return a new {@link InputStream} instance, not linked with network resources
|
* @return a new {@link InputStream} instance, not linked with network resources
|
||||||
* @throws RundeckApiException in case of error when calling the API
|
* @throws RundeckApiException in case of error when calling the API
|
||||||
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
|
* @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 RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
*/
|
*/
|
||||||
public InputStream get(ApiPathBuilder apiPath) throws RundeckApiException, RundeckApiLoginException,
|
public InputStream get(OldApiPathBuilder apiPath) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException {
|
RundeckApiTokenException {
|
||||||
ByteArrayInputStream response = execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath));
|
ByteArrayInputStream response = execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath));
|
||||||
|
|
||||||
|
@ -195,14 +196,14 @@ class ApiCall {
|
||||||
* Execute an HTTP POST request to the RunDeck instance, on the given path. We will login first, and then execute
|
* Execute an HTTP POST 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.
|
* 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 apiPath on which we will make the HTTP request - see {@link OldApiPathBuilder}
|
||||||
* @param parser used to parse the response
|
* @param parser used to parse the response
|
||||||
* @return the result of the call, as formatted by the parser
|
* @return the result of the call, as formatted by the parser
|
||||||
* @throws RundeckApiException in case of error when calling the API
|
* @throws RundeckApiException in case of error when calling the API
|
||||||
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
|
* @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 RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
*/
|
*/
|
||||||
public <T> T post(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
public <T> T post(OldApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||||
RundeckApiLoginException, RundeckApiTokenException {
|
RundeckApiLoginException, RundeckApiTokenException {
|
||||||
HttpPost httpPost = new HttpPost(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath);
|
HttpPost httpPost = new HttpPost(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath);
|
||||||
|
|
||||||
|
@ -220,14 +221,14 @@ class ApiCall {
|
||||||
* Execute an HTTP DELETE request to the RunDeck instance, on the given path. We will login first, and then execute
|
* 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.
|
* 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 apiPath on which we will make the HTTP request - see {@link OldApiPathBuilder}
|
||||||
* @param parser used to parse the response
|
* @param parser used to parse the response
|
||||||
* @return the result of the call, as formatted by the parser
|
* @return the result of the call, as formatted by the parser
|
||||||
* @throws RundeckApiException in case of error when calling the API
|
* @throws RundeckApiException in case of error when calling the API
|
||||||
* @throws RundeckApiLoginException if the login fails (in case of login-based authentication)
|
* @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 RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
*/
|
*/
|
||||||
public <T> T delete(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
public <T> T delete(OldApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||||
RundeckApiLoginException, RundeckApiTokenException {
|
RundeckApiLoginException, RundeckApiTokenException {
|
||||||
return execute(new HttpDelete(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath), parser);
|
return execute(new HttpDelete(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath), parser);
|
||||||
}
|
}
|
||||||
|
|
220
src/main/java/org/rundeck/api/OldApiPathBuilder.java
Normal file
220
src/main/java/org/rundeck/api/OldApiPathBuilder.java
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.rundeck.api.util.ParametersUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for API paths
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
class OldApiPathBuilder {
|
||||||
|
|
||||||
|
/** Internally, we store everything in a {@link StringBuilder} */
|
||||||
|
private final StringBuilder apiPath;
|
||||||
|
|
||||||
|
/** When POSTing, we can add attachments */
|
||||||
|
private final Map<String, InputStream> attachments;
|
||||||
|
|
||||||
|
/** Marker for using the right separator between parameters ("?" or "&") */
|
||||||
|
private boolean firstParamDone = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new instance, for the given "path" (the "path" is the part before the parameters. The path and the
|
||||||
|
* parameters are separated by a "?")
|
||||||
|
*
|
||||||
|
* @param paths elements of the path
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder(String... paths) {
|
||||||
|
apiPath = new StringBuilder();
|
||||||
|
attachments = new HashMap<String, InputStream>();
|
||||||
|
if (paths != null) {
|
||||||
|
for (String path : paths) {
|
||||||
|
if (StringUtils.isNotBlank(path)) {
|
||||||
|
append(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given parameter (key and value). This will only append the parameter if it is not blank (null, empty
|
||||||
|
* or whitespace), and make sure to add the right separator ("?" or "&") before. The key and value will be separated
|
||||||
|
* by the "=" character. Also, the value will be url-encoded.
|
||||||
|
*
|
||||||
|
* @param key of the parameter. Must not be null or empty
|
||||||
|
* @param value of the parameter. May be null/empty/blank. Will be url-encoded.
|
||||||
|
* @return this, for method chaining
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder param(String key, String value) {
|
||||||
|
if (StringUtils.isNotBlank(value)) {
|
||||||
|
appendSeparator();
|
||||||
|
append(key);
|
||||||
|
append("=");
|
||||||
|
append(ParametersUtil.urlEncode(value));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given parameter (key and value). This will only append the parameter if it is not null, and make sure
|
||||||
|
* to add the right separator ("?" or "&") before. The key and value will be separated by the "=" character. Also,
|
||||||
|
* the value will be converted to lower-case.
|
||||||
|
*
|
||||||
|
* @param key of the parameter. Must not be null or empty
|
||||||
|
* @param value of the parameter. May be null
|
||||||
|
* @return this, for method chaining
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder param(String key, Enum<?> value) {
|
||||||
|
if (value != null) {
|
||||||
|
param(key, StringUtils.lowerCase(value.toString()));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given parameter (key and value). This will only append the parameter if it is not null, and make sure
|
||||||
|
* to add the right separator ("?" or "&") before. The key and value will be separated by the "=" character.
|
||||||
|
*
|
||||||
|
* @param key of the parameter. Must not be null or empty
|
||||||
|
* @param value of the parameter. May be null
|
||||||
|
* @return this, for method chaining
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder param(String key, Date value) {
|
||||||
|
if (value != null) {
|
||||||
|
param(key, value.getTime());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given parameter (key and value). This will only append the parameter if it is not null, and make sure
|
||||||
|
* to add the right separator ("?" or "&") before. The key and value will be separated by the "=" character.
|
||||||
|
*
|
||||||
|
* @param key of the parameter. Must not be null or empty
|
||||||
|
* @param value of the parameter. May be null
|
||||||
|
* @return this, for method chaining
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder param(String key, Long value) {
|
||||||
|
if (value != null) {
|
||||||
|
param(key, value.toString());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given parameter (key and value). This will only append the parameter if it is not null, and make sure
|
||||||
|
* to add the right separator ("?" or "&") before. The key and value will be separated by the "=" character.
|
||||||
|
*
|
||||||
|
* @param key of the parameter. Must not be null or empty
|
||||||
|
* @param value of the parameter. May be null
|
||||||
|
* @return this, for method chaining
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder param(String key, Integer value) {
|
||||||
|
if (value != null) {
|
||||||
|
param(key, value.toString());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given parameter (key and value). This will only append the parameter if it is not null, and make sure
|
||||||
|
* to add the right separator ("?" or "&") before. The key and value will be separated by the "=" character.
|
||||||
|
*
|
||||||
|
* @param key of the parameter. Must not be null or empty
|
||||||
|
* @param value of the parameter. May be null
|
||||||
|
* @return this, for method chaining
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder param(String key, Boolean value) {
|
||||||
|
if (value != null) {
|
||||||
|
param(key, value.toString());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given node filters, only if it is not null/empty
|
||||||
|
*
|
||||||
|
* @param nodeFilters may be null/empty
|
||||||
|
* @return this, for method chaining
|
||||||
|
* @see ParametersUtil#generateNodeFiltersString(Properties)
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder nodeFilters(Properties nodeFilters) {
|
||||||
|
String filters = ParametersUtil.generateNodeFiltersString(nodeFilters);
|
||||||
|
if (StringUtils.isNotBlank(filters)) {
|
||||||
|
appendSeparator();
|
||||||
|
append(filters);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When POSTing a request, add the given {@link InputStream} as an attachment to the content of the request. This
|
||||||
|
* will only add the stream if it is not null.
|
||||||
|
*
|
||||||
|
* @param name of the attachment. Must not be null or empty
|
||||||
|
* @param stream. May be null
|
||||||
|
* @return this, for method chaining
|
||||||
|
*/
|
||||||
|
public OldApiPathBuilder attach(String name, InputStream stream) {
|
||||||
|
if (stream != null) {
|
||||||
|
attachments.put(name, stream);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return all attachments to be POSTed, with their names
|
||||||
|
*/
|
||||||
|
public Map<String, InputStream> getAttachments() {
|
||||||
|
return attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return apiPath.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the given string
|
||||||
|
*
|
||||||
|
* @param str to append
|
||||||
|
*/
|
||||||
|
private void append(String str) {
|
||||||
|
apiPath.append(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the right separator "?" or "&" between 2 parameters
|
||||||
|
*/
|
||||||
|
private void appendSeparator() {
|
||||||
|
if (firstParamDone) {
|
||||||
|
append("&");
|
||||||
|
} else {
|
||||||
|
append("?");
|
||||||
|
firstParamDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -47,9 +47,16 @@ import org.rundeck.api.parser.JobParser;
|
||||||
import org.rundeck.api.parser.JobsImportResultParser;
|
import org.rundeck.api.parser.JobsImportResultParser;
|
||||||
import org.rundeck.api.parser.ListParser;
|
import org.rundeck.api.parser.ListParser;
|
||||||
import org.rundeck.api.parser.NodeParser;
|
import org.rundeck.api.parser.NodeParser;
|
||||||
import org.rundeck.api.parser.ProjectParser;
|
|
||||||
import org.rundeck.api.parser.StringParser;
|
import org.rundeck.api.parser.StringParser;
|
||||||
import org.rundeck.api.parser.SystemInfoParser;
|
import org.rundeck.api.parser.SystemInfoParser;
|
||||||
|
import org.rundeck.api.request.AuthRequest;
|
||||||
|
import org.rundeck.api.request.HistoryRequest;
|
||||||
|
import org.rundeck.api.request.JobRunRequest;
|
||||||
|
import org.rundeck.api.request.JobTriggerRequest;
|
||||||
|
import org.rundeck.api.request.JobsListingRequest;
|
||||||
|
import org.rundeck.api.request.PingRequest;
|
||||||
|
import org.rundeck.api.request.ProjectDetailsRequest;
|
||||||
|
import org.rundeck.api.request.ProjectsListingRequest;
|
||||||
import org.rundeck.api.util.AssertUtil;
|
import org.rundeck.api.util.AssertUtil;
|
||||||
import org.rundeck.api.util.ParametersUtil;
|
import org.rundeck.api.util.ParametersUtil;
|
||||||
|
|
||||||
|
@ -154,7 +161,7 @@ public class RundeckClient implements Serializable {
|
||||||
* @throws RundeckApiException if the ping fails
|
* @throws RundeckApiException if the ping fails
|
||||||
*/
|
*/
|
||||||
public void ping() throws RundeckApiException {
|
public void ping() throws RundeckApiException {
|
||||||
new ApiCall(this).ping();
|
new PingRequest(this).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,7 +171,7 @@ public class RundeckClient implements Serializable {
|
||||||
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
*/
|
*/
|
||||||
public void testAuth() throws RundeckApiLoginException, RundeckApiTokenException {
|
public void testAuth() throws RundeckApiLoginException, RundeckApiTokenException {
|
||||||
new ApiCall(this).testAuth();
|
new AuthRequest(this).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,6 +183,38 @@ public class RundeckClient implements Serializable {
|
||||||
testAuth();
|
testAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New-style API
|
||||||
|
*/
|
||||||
|
|
||||||
|
public ProjectsListingRequest newProjectsListingRequest() {
|
||||||
|
return new ProjectsListingRequest(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectDetailsRequest newProjectDetailsRequest(String projectName) {
|
||||||
|
return new ProjectDetailsRequest(this, projectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobsListingRequest newJobsListingRequest(String project) {
|
||||||
|
return new JobsListingRequest(this, project);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobTriggerRequest newJobTriggerRequest(String jobId) {
|
||||||
|
return new JobTriggerRequest(this, jobId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobRunRequest newJobRunRequest(String jobId) {
|
||||||
|
return new JobRunRequest(this, jobId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HistoryRequest newHistoryRequest(String project) {
|
||||||
|
return new HistoryRequest(this, project);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Old-style API
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Projects
|
* Projects
|
||||||
*/
|
*/
|
||||||
|
@ -190,8 +229,7 @@ public class RundeckClient implements Serializable {
|
||||||
*/
|
*/
|
||||||
public List<RundeckProject> getProjects() throws RundeckApiException, RundeckApiLoginException,
|
public List<RundeckProject> getProjects() throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException {
|
RundeckApiTokenException {
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/projects"),
|
return newProjectsListingRequest().execute();
|
||||||
new ListParser<RundeckProject>(new ProjectParser(), "result/projects/project"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -206,9 +244,7 @@ public class RundeckClient implements Serializable {
|
||||||
*/
|
*/
|
||||||
public RundeckProject getProject(String projectName) throws RundeckApiException, RundeckApiLoginException,
|
public RundeckProject getProject(String projectName) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(projectName, "projectName is mandatory to get the details of a project !");
|
return newProjectDetailsRequest(projectName).execute();
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/project/", projectName),
|
|
||||||
new ProjectParser("result/projects/project"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -244,7 +280,7 @@ public class RundeckClient implements Serializable {
|
||||||
*/
|
*/
|
||||||
public List<RundeckJob> getJobs(String project) throws RundeckApiException, RundeckApiLoginException,
|
public List<RundeckJob> getJobs(String project) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
return getJobs(project, null, null, new String[0]);
|
return newJobsListingRequest(project).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -264,10 +300,10 @@ public class RundeckClient implements Serializable {
|
||||||
public List<RundeckJob> getJobs(String project, String jobFilter, String groupPath, String... jobIds)
|
public List<RundeckJob> getJobs(String project, String jobFilter, String groupPath, String... jobIds)
|
||||||
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(project, "project is mandatory to get all jobs !");
|
AssertUtil.notBlank(project, "project is mandatory to get all jobs !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/jobs").param("project", project)
|
return new ApiCall(this).get(new OldApiPathBuilder("/jobs").param("project", project)
|
||||||
.param("jobFilter", jobFilter)
|
.param("jobFilter", jobFilter)
|
||||||
.param("groupPath", groupPath)
|
.param("groupPath", groupPath)
|
||||||
.param("idlist", StringUtils.join(jobIds, ",")),
|
.param("idlist", StringUtils.join(jobIds, ",")),
|
||||||
new ListParser<RundeckJob>(new JobParser(), "result/jobs/job"));
|
new ListParser<RundeckJob>(new JobParser(), "result/jobs/job"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,11 +486,12 @@ public class RundeckClient implements Serializable {
|
||||||
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notNull(format, "format is mandatory to export jobs !");
|
AssertUtil.notNull(format, "format is mandatory to export jobs !");
|
||||||
AssertUtil.notBlank(project, "project is mandatory to export jobs !");
|
AssertUtil.notBlank(project, "project is mandatory to export jobs !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/jobs/export").param("format", format)
|
return new ApiCall(this).get(new OldApiPathBuilder("/jobs/export").param("format", format)
|
||||||
.param("project", project)
|
.param("project", project)
|
||||||
.param("jobFilter", jobFilter)
|
.param("jobFilter", jobFilter)
|
||||||
.param("groupPath", groupPath)
|
.param("groupPath", groupPath)
|
||||||
.param("idlist", StringUtils.join(jobIds, ",")));
|
.param("idlist",
|
||||||
|
StringUtils.join(jobIds, ",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -538,7 +575,7 @@ public class RundeckClient implements Serializable {
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notNull(format, "format is mandatory to export a job !");
|
AssertUtil.notNull(format, "format is mandatory to export a job !");
|
||||||
AssertUtil.notBlank(jobId, "jobId is mandatory to export a job !");
|
AssertUtil.notBlank(jobId, "jobId is mandatory to export a job !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/job/", jobId).param("format", format));
|
return new ApiCall(this).get(new OldApiPathBuilder("/job/", jobId).param("format", format));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -712,9 +749,9 @@ public class RundeckClient implements Serializable {
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notNull(stream, "inputStream of jobs is mandatory to import jobs !");
|
AssertUtil.notNull(stream, "inputStream of jobs is mandatory to import jobs !");
|
||||||
AssertUtil.notNull(fileType, "fileType is mandatory to import jobs !");
|
AssertUtil.notNull(fileType, "fileType is mandatory to import jobs !");
|
||||||
return new ApiCall(this).post(new ApiPathBuilder("/jobs/import").param("format", fileType)
|
return new ApiCall(this).post(new OldApiPathBuilder("/jobs/import").param("format", fileType)
|
||||||
.param("dupeOption", importBehavior)
|
.param("dupeOption", importBehavior)
|
||||||
.attach("xmlBatch", stream),
|
.attach("xmlBatch", stream),
|
||||||
new JobsImportResultParser("result"));
|
new JobsImportResultParser("result"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,7 +792,7 @@ public class RundeckClient implements Serializable {
|
||||||
public RundeckJob getJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
|
public RundeckJob getJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(jobId, "jobId is mandatory to get the details of a job !");
|
AssertUtil.notBlank(jobId, "jobId is mandatory to get the details of a job !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/job/", jobId), new JobParser("joblist/job"));
|
return new ApiCall(this).get(new OldApiPathBuilder("/job/", jobId), new JobParser("joblist/job"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -771,7 +808,8 @@ public class RundeckClient implements Serializable {
|
||||||
public String deleteJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
|
public String deleteJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(jobId, "jobId is mandatory to delete a job !");
|
AssertUtil.notBlank(jobId, "jobId is mandatory to delete a job !");
|
||||||
return new ApiCall(this).delete(new ApiPathBuilder("/job/", jobId), new StringParser("result/success/message"));
|
return new ApiCall(this).delete(new OldApiPathBuilder("/job/", jobId),
|
||||||
|
new StringParser("result/success/message"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -829,11 +867,7 @@ public class RundeckClient implements Serializable {
|
||||||
*/
|
*/
|
||||||
public RundeckExecution triggerJob(String jobId, Properties options, Properties nodeFilters)
|
public RundeckExecution triggerJob(String jobId, Properties options, Properties nodeFilters)
|
||||||
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(jobId, "jobId is mandatory to trigger a job !");
|
return newJobTriggerRequest(jobId).addOptions(options).filterNodes(nodeFilters).execute();
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/job/", jobId, "/run").param("argString",
|
|
||||||
ParametersUtil.generateArgString(options))
|
|
||||||
.nodeFilters(nodeFilters),
|
|
||||||
new ExecutionParser("result/executions/execution"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -941,24 +975,10 @@ public class RundeckClient implements Serializable {
|
||||||
public RundeckExecution runJob(String jobId, Properties options, Properties nodeFilters, long poolingInterval,
|
public RundeckExecution runJob(String jobId, Properties options, Properties nodeFilters, long poolingInterval,
|
||||||
TimeUnit poolingUnit) throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException,
|
TimeUnit poolingUnit) throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException,
|
||||||
IllegalArgumentException {
|
IllegalArgumentException {
|
||||||
if (poolingInterval <= 0) {
|
return newJobRunRequest(jobId).addOptions(options)
|
||||||
poolingInterval = DEFAULT_POOLING_INTERVAL;
|
.filterNodes(nodeFilters)
|
||||||
poolingUnit = DEFAULT_POOLING_UNIT;
|
.poolingInterval(poolingInterval, poolingUnit)
|
||||||
}
|
.execute();
|
||||||
if (poolingUnit == null) {
|
|
||||||
poolingUnit = DEFAULT_POOLING_UNIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
RundeckExecution execution = triggerJob(jobId, options, nodeFilters);
|
|
||||||
while (ExecutionStatus.RUNNING.equals(execution.getStatus())) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(poolingUnit.toMillis(poolingInterval));
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
execution = getExecution(execution.getId());
|
|
||||||
}
|
|
||||||
return execution;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1026,13 +1046,14 @@ public class RundeckClient implements Serializable {
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(project, "project is mandatory to trigger an ad-hoc command !");
|
AssertUtil.notBlank(project, "project is mandatory to trigger an ad-hoc command !");
|
||||||
AssertUtil.notBlank(command, "command is mandatory to trigger an ad-hoc command !");
|
AssertUtil.notBlank(command, "command is mandatory to trigger an ad-hoc command !");
|
||||||
RundeckExecution execution = new ApiCall(this).get(new ApiPathBuilder("/run/command").param("project", project)
|
RundeckExecution execution = new ApiCall(this).get(new OldApiPathBuilder("/run/command").param("project",
|
||||||
.param("exec", command)
|
project)
|
||||||
.param("nodeThreadcount",
|
.param("exec", command)
|
||||||
nodeThreadcount)
|
.param("nodeThreadcount",
|
||||||
.param("nodeKeepgoing",
|
nodeThreadcount)
|
||||||
nodeKeepgoing)
|
.param("nodeKeepgoing",
|
||||||
.nodeFilters(nodeFilters),
|
nodeKeepgoing)
|
||||||
|
.nodeFilters(nodeFilters),
|
||||||
new ExecutionParser("result/execution"));
|
new ExecutionParser("result/execution"));
|
||||||
// the first call just returns the ID of the execution, so we need another call to get a "real" execution
|
// the first call just returns the ID of the execution, so we need another call to get a "real" execution
|
||||||
return getExecution(execution.getId());
|
return getExecution(execution.getId());
|
||||||
|
@ -1385,16 +1406,17 @@ public class RundeckClient implements Serializable {
|
||||||
RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(project, "project is mandatory to trigger an ad-hoc script !");
|
AssertUtil.notBlank(project, "project is mandatory to trigger an ad-hoc script !");
|
||||||
AssertUtil.notNull(script, "script is mandatory to trigger an ad-hoc script !");
|
AssertUtil.notNull(script, "script is mandatory to trigger an ad-hoc script !");
|
||||||
RundeckExecution execution = new ApiCall(this).post(new ApiPathBuilder("/run/script").param("project", project)
|
RundeckExecution execution = new ApiCall(this).post(new OldApiPathBuilder("/run/script").param("project",
|
||||||
.attach("scriptFile",
|
project)
|
||||||
script)
|
.attach("scriptFile",
|
||||||
.param("argString",
|
script)
|
||||||
ParametersUtil.generateArgString(options))
|
.param("argString",
|
||||||
.param("nodeThreadcount",
|
ParametersUtil.generateArgString(options))
|
||||||
nodeThreadcount)
|
.param("nodeThreadcount",
|
||||||
.param("nodeKeepgoing",
|
nodeThreadcount)
|
||||||
nodeKeepgoing)
|
.param("nodeKeepgoing",
|
||||||
.nodeFilters(nodeFilters),
|
nodeKeepgoing)
|
||||||
|
.nodeFilters(nodeFilters),
|
||||||
new ExecutionParser("result/execution"));
|
new ExecutionParser("result/execution"));
|
||||||
// the first call just returns the ID of the execution, so we need another call to get a "real" execution
|
// the first call just returns the ID of the execution, so we need another call to get a "real" execution
|
||||||
return getExecution(execution.getId());
|
return getExecution(execution.getId());
|
||||||
|
@ -1890,7 +1912,7 @@ public class RundeckClient implements Serializable {
|
||||||
public List<RundeckExecution> getRunningExecutions(String project) throws RundeckApiException,
|
public List<RundeckExecution> getRunningExecutions(String project) throws RundeckApiException,
|
||||||
RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(project, "project is mandatory get all running executions !");
|
AssertUtil.notBlank(project, "project is mandatory get all running executions !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/executions/running").param("project", project),
|
return new ApiCall(this).get(new OldApiPathBuilder("/executions/running").param("project", project),
|
||||||
new ListParser<RundeckExecution>(new ExecutionParser(),
|
new ListParser<RundeckExecution>(new ExecutionParser(),
|
||||||
"result/executions/execution"));
|
"result/executions/execution"));
|
||||||
}
|
}
|
||||||
|
@ -1986,9 +2008,9 @@ public class RundeckClient implements Serializable {
|
||||||
public List<RundeckExecution> getJobExecutions(String jobId, ExecutionStatus status, Long max, Long offset)
|
public List<RundeckExecution> getJobExecutions(String jobId, ExecutionStatus status, Long max, Long offset)
|
||||||
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(jobId, "jobId is mandatory to get the executions of a job !");
|
AssertUtil.notBlank(jobId, "jobId is mandatory to get the executions of a job !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/job/", jobId, "/executions").param("status", status)
|
return new ApiCall(this).get(new OldApiPathBuilder("/job/", jobId, "/executions").param("status", status)
|
||||||
.param("max", max)
|
.param("max", max)
|
||||||
.param("offset", offset),
|
.param("offset", offset),
|
||||||
new ListParser<RundeckExecution>(new ExecutionParser(),
|
new ListParser<RundeckExecution>(new ExecutionParser(),
|
||||||
"result/executions/execution"));
|
"result/executions/execution"));
|
||||||
}
|
}
|
||||||
|
@ -2006,7 +2028,7 @@ public class RundeckClient implements Serializable {
|
||||||
public RundeckExecution getExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException,
|
public RundeckExecution getExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notNull(executionId, "executionId is mandatory to get the details of an execution !");
|
AssertUtil.notNull(executionId, "executionId is mandatory to get the details of an execution !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/execution/", executionId.toString()),
|
return new ApiCall(this).get(new OldApiPathBuilder("/execution/", executionId.toString()),
|
||||||
new ExecutionParser("result/executions/execution"));
|
new ExecutionParser("result/executions/execution"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2023,7 +2045,7 @@ public class RundeckClient implements Serializable {
|
||||||
public RundeckAbort abortExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException,
|
public RundeckAbort abortExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notNull(executionId, "executionId is mandatory to abort an execution !");
|
AssertUtil.notNull(executionId, "executionId is mandatory to abort an execution !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/execution/", executionId.toString(), "/abort"),
|
return new ApiCall(this).get(new OldApiPathBuilder("/execution/", executionId.toString(), "/abort"),
|
||||||
new AbortParser("result/abort"));
|
new AbortParser("result/abort"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2207,15 +2229,15 @@ public class RundeckClient implements Serializable {
|
||||||
Date begin, Date end, Long max, Long offset) throws RundeckApiException, RundeckApiLoginException,
|
Date begin, Date end, Long max, Long offset) throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(project, "project is mandatory to get the history !");
|
AssertUtil.notBlank(project, "project is mandatory to get the history !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/history").param("project", project)
|
return new ApiCall(this).get(new OldApiPathBuilder("/history").param("project", project)
|
||||||
.param("jobIdFilter", jobId)
|
.param("jobIdFilter", jobId)
|
||||||
.param("reportIdFilter", reportId)
|
.param("reportIdFilter", reportId)
|
||||||
.param("userFilter", user)
|
.param("userFilter", user)
|
||||||
.param("recentFilter", recent)
|
.param("recentFilter", recent)
|
||||||
.param("begin", begin)
|
.param("begin", begin)
|
||||||
.param("end", end)
|
.param("end", end)
|
||||||
.param("max", max)
|
.param("max", max)
|
||||||
.param("offset", offset),
|
.param("offset", offset),
|
||||||
new HistoryParser("result/events"));
|
new HistoryParser("result/events"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2269,8 +2291,8 @@ public class RundeckClient implements Serializable {
|
||||||
public List<RundeckNode> getNodes(String project, Properties nodeFilters) throws RundeckApiException,
|
public List<RundeckNode> getNodes(String project, Properties nodeFilters) throws RundeckApiException,
|
||||||
RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(project, "project is mandatory to get all nodes !");
|
AssertUtil.notBlank(project, "project is mandatory to get all nodes !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/resources").param("project", project)
|
return new ApiCall(this).get(new OldApiPathBuilder("/resources").param("project", project)
|
||||||
.nodeFilters(nodeFilters),
|
.nodeFilters(nodeFilters),
|
||||||
new ListParser<RundeckNode>(new NodeParser(), "project/node"));
|
new ListParser<RundeckNode>(new NodeParser(), "project/node"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2289,7 +2311,7 @@ public class RundeckClient implements Serializable {
|
||||||
RundeckApiTokenException, IllegalArgumentException {
|
RundeckApiTokenException, IllegalArgumentException {
|
||||||
AssertUtil.notBlank(name, "the name of the node is mandatory to get a node !");
|
AssertUtil.notBlank(name, "the name of the node is mandatory to get a node !");
|
||||||
AssertUtil.notBlank(project, "project is mandatory to get a node !");
|
AssertUtil.notBlank(project, "project is mandatory to get a node !");
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/resource/", name).param("project", project),
|
return new ApiCall(this).get(new OldApiPathBuilder("/resource/", name).param("project", project),
|
||||||
new NodeParser("project/node"));
|
new NodeParser("project/node"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2307,7 +2329,7 @@ public class RundeckClient implements Serializable {
|
||||||
*/
|
*/
|
||||||
public RundeckSystemInfo getSystemInfo() throws RundeckApiException, RundeckApiLoginException,
|
public RundeckSystemInfo getSystemInfo() throws RundeckApiException, RundeckApiLoginException,
|
||||||
RundeckApiTokenException {
|
RundeckApiTokenException {
|
||||||
return new ApiCall(this).get(new ApiPathBuilder("/system/info"), new SystemInfoParser("result/system"));
|
return new ApiCall(this).get(new OldApiPathBuilder("/system/info"), new SystemInfoParser("result/system"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.rundeck.api;
|
package org.rundeck.api.request;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
444
src/main/java/org/rundeck/api/request/ApiRequest.java
Normal file
444
src/main/java/org/rundeck/api/request/ApiRequest.java
Normal file
|
@ -0,0 +1,444 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.ProxySelector;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.UnrecoverableKeyException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.http.HttpException;
|
||||||
|
import org.apache.http.HttpRequest;
|
||||||
|
import org.apache.http.HttpRequestInterceptor;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
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;
|
||||||
|
import org.apache.http.entity.mime.HttpMultipartMode;
|
||||||
|
import org.apache.http.entity.mime.MultipartEntity;
|
||||||
|
import org.apache.http.entity.mime.content.InputStreamBody;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.apache.http.params.HttpProtocolParams;
|
||||||
|
import org.apache.http.protocol.HTTP;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.rundeck.api.RundeckApiException;
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
import org.rundeck.api.RundeckApiException.RundeckApiLoginException;
|
||||||
|
import org.rundeck.api.RundeckApiException.RundeckApiTokenException;
|
||||||
|
import org.rundeck.api.parser.ParserHelper;
|
||||||
|
import org.rundeck.api.parser.XmlNodeParser;
|
||||||
|
import org.rundeck.api.util.AssertUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
abstract class ApiRequest<T> {
|
||||||
|
|
||||||
|
/** RunDeck HTTP header for the auth-token (in case of token-based authentication) */
|
||||||
|
private static final transient String AUTH_TOKEN_HEADER = "X-RunDeck-Auth-Token";
|
||||||
|
|
||||||
|
/** {@link RundeckClient} instance holding the RunDeck url and the credentials */
|
||||||
|
protected final RundeckClient client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @param client
|
||||||
|
*/
|
||||||
|
protected ApiRequest(RundeckClient client) {
|
||||||
|
super();
|
||||||
|
this.client = client;
|
||||||
|
AssertUtil.notNull(client, "The RunDeck Client must not be null !");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract T execute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to "ping" the RunDeck instance to see if it is alive
|
||||||
|
*
|
||||||
|
* @throws RundeckApiException if the ping fails
|
||||||
|
*/
|
||||||
|
protected void ping() throws RundeckApiException {
|
||||||
|
HttpClient httpClient = instantiateHttpClient();
|
||||||
|
try {
|
||||||
|
HttpResponse response = httpClient.execute(new HttpGet(client.getUrl()));
|
||||||
|
if (response.getStatusLine().getStatusCode() / 100 != 2) {
|
||||||
|
throw new RundeckApiException("Invalid HTTP response '" + response.getStatusLine() + "' when pinging "
|
||||||
|
+ client.getUrl());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RundeckApiException("Failed to ping RunDeck instance at " + client.getUrl(), e);
|
||||||
|
} finally {
|
||||||
|
httpClient.getConnectionManager().shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the authentication on the RunDeck instance. Will delegate to either {@link #testLoginAuth()} (in case of
|
||||||
|
* login-based auth) or {@link #testTokenAuth()} (in case of token-based auth).
|
||||||
|
*
|
||||||
|
* @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)
|
||||||
|
* @see #testLoginAuth()
|
||||||
|
* @see #testTokenAuth()
|
||||||
|
*/
|
||||||
|
protected void testAuth() throws RundeckApiLoginException, RundeckApiTokenException {
|
||||||
|
if (client.getToken() != null) {
|
||||||
|
testTokenAuth();
|
||||||
|
} else {
|
||||||
|
testLoginAuth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the login-based authentication on the RunDeck instance
|
||||||
|
*
|
||||||
|
* @throws RundeckApiLoginException if the login fails
|
||||||
|
* @see #testAuth()
|
||||||
|
*/
|
||||||
|
protected void testLoginAuth() throws RundeckApiLoginException {
|
||||||
|
HttpClient httpClient = instantiateHttpClient();
|
||||||
|
try {
|
||||||
|
login(httpClient);
|
||||||
|
} finally {
|
||||||
|
httpClient.getConnectionManager().shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the token-based authentication on the RunDeck instance
|
||||||
|
*
|
||||||
|
* @throws RundeckApiTokenException if the token is invalid
|
||||||
|
* @see #testAuth()
|
||||||
|
*/
|
||||||
|
protected void testTokenAuth() throws RundeckApiTokenException {
|
||||||
|
try {
|
||||||
|
execute(new HttpGet(client.getUrl() + RundeckClient.API_ENDPOINT + "/system/info"));
|
||||||
|
} catch (RundeckApiTokenException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (RundeckApiException e) {
|
||||||
|
throw new RundeckApiTokenException("Failed to verify token", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an HTTP GET 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 (in case of login-based authentication)
|
||||||
|
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
|
*/
|
||||||
|
protected T get(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||||
|
RundeckApiLoginException, RundeckApiTokenException {
|
||||||
|
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 (in case of login-based authentication)
|
||||||
|
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
|
*/
|
||||||
|
protected InputStream get(ApiPathBuilder apiPath) throws RundeckApiException, RundeckApiLoginException,
|
||||||
|
RundeckApiTokenException {
|
||||||
|
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 POST 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 (in case of login-based authentication)
|
||||||
|
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
|
*/
|
||||||
|
protected T post(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||||
|
RundeckApiLoginException, RundeckApiTokenException {
|
||||||
|
HttpPost httpPost = new HttpPost(client.getUrl() + RundeckClient.API_ENDPOINT + apiPath);
|
||||||
|
|
||||||
|
// POST a multi-part request, with all attachments
|
||||||
|
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
|
||||||
|
for (Entry<String, InputStream> attachment : apiPath.getAttachments().entrySet()) {
|
||||||
|
entity.addPart(attachment.getKey(), new InputStreamBody(attachment.getValue(), attachment.getKey()));
|
||||||
|
}
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
|
||||||
|
return execute(httpPost, 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 (in case of login-based authentication)
|
||||||
|
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
|
*/
|
||||||
|
protected T delete(ApiPathBuilder apiPath, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||||
|
RundeckApiLoginException, RundeckApiTokenException {
|
||||||
|
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 (in case of login-based authentication)
|
||||||
|
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
|
*/
|
||||||
|
private T execute(HttpRequestBase request, XmlNodeParser<T> parser) throws RundeckApiException,
|
||||||
|
RundeckApiLoginException, RundeckApiTokenException {
|
||||||
|
// 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 (in case of login-based authentication)
|
||||||
|
* @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication)
|
||||||
|
*/
|
||||||
|
private ByteArrayInputStream execute(HttpRequestBase request) throws RundeckApiException, RundeckApiLoginException,
|
||||||
|
RundeckApiTokenException {
|
||||||
|
HttpClient httpClient = instantiateHttpClient();
|
||||||
|
try {
|
||||||
|
// we only need to manually login in case of login-based authentication
|
||||||
|
// note that in case of token-based auth, the auth (via an HTTP header) is managed by an interceptor.
|
||||||
|
if (client.getToken() == null) {
|
||||||
|
login(httpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute the HTTP request
|
||||||
|
HttpResponse response = null;
|
||||||
|
try {
|
||||||
|
response = httpClient.execute(request);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RundeckApiException("Failed to execute an HTTP " + request.getMethod() + " on url : "
|
||||||
|
+ request.getURI(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case of error, we get a redirect to /api/error
|
||||||
|
// that we need to follow manually for POST and DELETE requests (as GET)
|
||||||
|
if (response.getStatusLine().getStatusCode() / 100 == 3) {
|
||||||
|
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 HttpGet(newLocation);
|
||||||
|
try {
|
||||||
|
response = httpClient.execute(request);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RundeckApiException("Failed to execute an HTTP GET on url : " + request.getURI(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
if (response.getStatusLine().getStatusCode() == 403 && client.getToken() != null) {
|
||||||
|
throw new RundeckApiTokenException("Invalid Token ! Got HTTP response '" + response.getStatusLine()
|
||||||
|
+ "' for " + request.getURI());
|
||||||
|
} else {
|
||||||
|
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 : "
|
||||||
|
+ response.getStatusLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
// return a new inputStream, so that we can close all network resources
|
||||||
|
try {
|
||||||
|
return new ByteArrayInputStream(EntityUtils.toByteArray(response.getEntity()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RundeckApiException("Failed to consume entity and convert the inputStream", e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
httpClient.getConnectionManager().shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the actual work of login, using the given {@link HttpClient} instance. You'll need to re-use this instance
|
||||||
|
* when making API calls (such as running a job). Only use this in case of login-based authentication.
|
||||||
|
*
|
||||||
|
* @param httpClient pre-instantiated
|
||||||
|
* @throws RundeckApiLoginException if the login failed
|
||||||
|
*/
|
||||||
|
private void login(HttpClient httpClient) throws RundeckApiLoginException {
|
||||||
|
String location = client.getUrl() + "/j_security_check";
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
HttpPost postLogin = new HttpPost(location);
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("j_username", client.getLogin()));
|
||||||
|
params.add(new BasicNameValuePair("j_password", client.getPassword()));
|
||||||
|
params.add(new BasicNameValuePair("action", "login"));
|
||||||
|
|
||||||
|
HttpResponse response = null;
|
||||||
|
try {
|
||||||
|
postLogin.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
|
||||||
|
response = httpClient.execute(postLogin);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RundeckApiLoginException("Failed to post login form on " + location, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.getStatusLine().getStatusCode() / 100 == 3) {
|
||||||
|
// HTTP client refuses to handle redirects (code 3xx) for POST, so we have to do it manually...
|
||||||
|
location = response.getFirstHeader("Location").getValue();
|
||||||
|
try {
|
||||||
|
EntityUtils.consume(response.getEntity());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RundeckApiLoginException("Failed to consume entity (release connection)", e);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (response.getStatusLine().getStatusCode() / 100 != 2) {
|
||||||
|
throw new RundeckApiLoginException("Invalid HTTP response '" + response.getStatusLine() + "' for "
|
||||||
|
+ location);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String content = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
|
||||||
|
if (StringUtils.contains(content, "j_security_check")) {
|
||||||
|
throw new RundeckApiLoginException("Login failed for user " + client.getLogin());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
EntityUtils.consume(response.getEntity());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RundeckApiLoginException("Failed to consume entity (release connection)", e);
|
||||||
|
}
|
||||||
|
} catch (IOException io) {
|
||||||
|
throw new RundeckApiLoginException("Failed to read RunDeck result", io);
|
||||||
|
} catch (ParseException p) {
|
||||||
|
throw new RundeckApiLoginException("Failed to parse RunDeck response", p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a new {@link HttpClient} instance, configured to accept all SSL certificates
|
||||||
|
*
|
||||||
|
* @return an {@link HttpClient} instance - won't be null
|
||||||
|
*/
|
||||||
|
private HttpClient instantiateHttpClient() {
|
||||||
|
DefaultHttpClient httpClient = new DefaultHttpClient();
|
||||||
|
|
||||||
|
// configure user-agent
|
||||||
|
HttpProtocolParams.setUserAgent(httpClient.getParams(), "RunDeck API Java Client " + RundeckClient.API_VERSION);
|
||||||
|
|
||||||
|
// configure SSL
|
||||||
|
SSLSocketFactory socketFactory = null;
|
||||||
|
try {
|
||||||
|
socketFactory = new SSLSocketFactory(new TrustStrategy() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||||
|
} catch (KeyManagementException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (UnrecoverableKeyException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (KeyStoreException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, socketFactory));
|
||||||
|
|
||||||
|
// configure proxy (use system env : http.proxyHost / http.proxyPort)
|
||||||
|
System.setProperty("java.net.useSystemProxies", "true");
|
||||||
|
httpClient.setRoutePlanner(new ProxySelectorRoutePlanner(httpClient.getConnectionManager().getSchemeRegistry(),
|
||||||
|
ProxySelector.getDefault()));
|
||||||
|
|
||||||
|
// in case of token-based authentication, add the correct HTTP header to all requests via an interceptor
|
||||||
|
httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
|
||||||
|
if (client.getToken() != null) {
|
||||||
|
request.addHeader(AUTH_TOKEN_HEADER, client.getToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
src/main/java/org/rundeck/api/request/AuthRequest.java
Normal file
36
src/main/java/org/rundeck/api/request/AuthRequest.java
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class AuthRequest extends ApiRequest<Void> {
|
||||||
|
|
||||||
|
public AuthRequest(RundeckClient client) {
|
||||||
|
super(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute() {
|
||||||
|
testAuth();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
83
src/main/java/org/rundeck/api/request/HistoryRequest.java
Normal file
83
src/main/java/org/rundeck/api/request/HistoryRequest.java
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
import org.rundeck.api.domain.RundeckHistory;
|
||||||
|
import org.rundeck.api.parser.HistoryParser;
|
||||||
|
import org.rundeck.api.util.AssertUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class HistoryRequest extends ApiRequest<RundeckHistory> {
|
||||||
|
|
||||||
|
private final String project;
|
||||||
|
|
||||||
|
private String jobId;
|
||||||
|
|
||||||
|
private String reportId;
|
||||||
|
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
private String recent;
|
||||||
|
|
||||||
|
private Date beginAt;
|
||||||
|
|
||||||
|
private Date end;
|
||||||
|
|
||||||
|
private Long max;
|
||||||
|
|
||||||
|
private Long offset;
|
||||||
|
|
||||||
|
public HistoryRequest(RundeckClient client, String project) {
|
||||||
|
super(client);
|
||||||
|
this.project = project;
|
||||||
|
AssertUtil.notBlank(project, "project is mandatory to get the history !");
|
||||||
|
}
|
||||||
|
|
||||||
|
public HistoryRequest beginAt(Date beginAt) {
|
||||||
|
this.beginAt = beginAt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HistoryRequest max(Long max) {
|
||||||
|
this.max = max;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HistoryRequest offset(Long offset) {
|
||||||
|
this.offset = offset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RundeckHistory execute() {
|
||||||
|
return get(new ApiPathBuilder("/history").param("project", project)
|
||||||
|
.param("jobIdFilter", jobId)
|
||||||
|
.param("reportIdFilter", reportId)
|
||||||
|
.param("userFilter", user)
|
||||||
|
.param("recentFilter", recent)
|
||||||
|
.param("begin", beginAt)
|
||||||
|
.param("end", end)
|
||||||
|
.param("max", max)
|
||||||
|
.param("offset", offset), new HistoryParser("result/events"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
72
src/main/java/org/rundeck/api/request/JobRunRequest.java
Normal file
72
src/main/java/org/rundeck/api/request/JobRunRequest.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
import org.rundeck.api.domain.RundeckExecution;
|
||||||
|
import org.rundeck.api.domain.RundeckExecution.ExecutionStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class JobRunRequest extends JobTriggerRequest<JobRunRequest> {
|
||||||
|
|
||||||
|
/** Default value for the "pooling interval" used when running jobs/commands/scripts */
|
||||||
|
public static final transient long DEFAULT_POOLING_INTERVAL = 5;
|
||||||
|
|
||||||
|
/** Default unit of the "pooling interval" used when running jobs/commands/scripts */
|
||||||
|
public static final transient TimeUnit DEFAULT_POOLING_UNIT = TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
private Long poolingInterval;
|
||||||
|
|
||||||
|
private TimeUnit poolingUnit;
|
||||||
|
|
||||||
|
public JobRunRequest(RundeckClient client, String project) {
|
||||||
|
super(client, project);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobRunRequest poolingInterval(Long poolingInterval, TimeUnit poolingUnit) {
|
||||||
|
this.poolingInterval = poolingInterval;
|
||||||
|
this.poolingUnit = poolingUnit;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RundeckExecution execute() {
|
||||||
|
if (poolingInterval <= 0) {
|
||||||
|
poolingInterval = DEFAULT_POOLING_INTERVAL;
|
||||||
|
poolingUnit = DEFAULT_POOLING_UNIT;
|
||||||
|
}
|
||||||
|
if (poolingUnit == null) {
|
||||||
|
poolingUnit = DEFAULT_POOLING_UNIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
RundeckExecution execution = super.execute();
|
||||||
|
while (ExecutionStatus.RUNNING.equals(execution.getStatus())) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(poolingUnit.toMillis(poolingInterval));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
execution = client.getExecution(execution.getId());
|
||||||
|
}
|
||||||
|
return execution;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
src/main/java/org/rundeck/api/request/JobTriggerRequest.java
Normal file
64
src/main/java/org/rundeck/api/request/JobTriggerRequest.java
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
import org.rundeck.api.domain.RundeckExecution;
|
||||||
|
import org.rundeck.api.parser.ExecutionParser;
|
||||||
|
import org.rundeck.api.util.AssertUtil;
|
||||||
|
import org.rundeck.api.util.ParametersUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class JobTriggerRequest<T extends JobTriggerRequest<?>> extends ApiRequest<RundeckExecution> {
|
||||||
|
|
||||||
|
private final String jobId;
|
||||||
|
|
||||||
|
private Properties options;
|
||||||
|
|
||||||
|
private Properties nodeFilters;
|
||||||
|
|
||||||
|
public JobTriggerRequest(RundeckClient client, String jobId) {
|
||||||
|
super(client);
|
||||||
|
this.jobId = jobId;
|
||||||
|
AssertUtil.notBlank(jobId, "jobId is mandatory !");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T addOptions(Properties options) {
|
||||||
|
this.options = options;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T filterNodes(Properties nodeFilters) {
|
||||||
|
this.nodeFilters = nodeFilters;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RundeckExecution execute() {
|
||||||
|
return get(new ApiPathBuilder("/job/", jobId, "/run").param("argString",
|
||||||
|
ParametersUtil.generateArgString(options))
|
||||||
|
.nodeFilters(nodeFilters),
|
||||||
|
new ExecutionParser("result/executions/execution"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
import org.rundeck.api.domain.RundeckJob;
|
||||||
|
import org.rundeck.api.parser.JobParser;
|
||||||
|
import org.rundeck.api.parser.ListParser;
|
||||||
|
import org.rundeck.api.util.AssertUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class JobsListingRequest extends ApiRequest<List<RundeckJob>> {
|
||||||
|
|
||||||
|
private final String project;
|
||||||
|
|
||||||
|
private String jobFilter;
|
||||||
|
|
||||||
|
public JobsListingRequest(RundeckClient client, String project) {
|
||||||
|
super(client);
|
||||||
|
this.project = project;
|
||||||
|
AssertUtil.notBlank(project, "project is mandatory to get all jobs !");
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobsListingRequest jobFilter(String jobFilter) {
|
||||||
|
this.jobFilter = jobFilter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RundeckJob> execute() {
|
||||||
|
return get(new ApiPathBuilder("/jobs").param("project", project).param("jobFilter", jobFilter),
|
||||||
|
new ListParser<RundeckJob>(new JobParser(), "result/jobs/job"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
src/main/java/org/rundeck/api/request/PingRequest.java
Normal file
37
src/main/java/org/rundeck/api/request/PingRequest.java
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class PingRequest extends ApiRequest<Void> {
|
||||||
|
|
||||||
|
public PingRequest(RundeckClient client) {
|
||||||
|
super(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute() {
|
||||||
|
ping();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
import org.rundeck.api.domain.RundeckProject;
|
||||||
|
import org.rundeck.api.parser.ProjectParser;
|
||||||
|
import org.rundeck.api.util.AssertUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class ProjectDetailsRequest extends ApiRequest<RundeckProject> {
|
||||||
|
|
||||||
|
private final String projectName;
|
||||||
|
|
||||||
|
public ProjectDetailsRequest(RundeckClient client, String projectName) {
|
||||||
|
super(client);
|
||||||
|
this.projectName = projectName;
|
||||||
|
AssertUtil.notBlank(projectName, "projectName is mandatory to get the details of a project !");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RundeckProject execute() {
|
||||||
|
return get(new ApiPathBuilder("/project/", projectName), new ProjectParser("result/projects/project"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.rundeck.api.RundeckClient;
|
||||||
|
import org.rundeck.api.domain.RundeckProject;
|
||||||
|
import org.rundeck.api.parser.ListParser;
|
||||||
|
import org.rundeck.api.parser.ProjectParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Vincent Behar
|
||||||
|
*/
|
||||||
|
public class ProjectsListingRequest extends ApiRequest<List<RundeckProject>> {
|
||||||
|
|
||||||
|
public ProjectsListingRequest(RundeckClient client) {
|
||||||
|
super(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RundeckProject> execute() {
|
||||||
|
return get(new ApiPathBuilder("/projects"), new ListParser<RundeckProject>(new ProjectParser(),
|
||||||
|
"result/projects/project"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue