mirror of
https://github.com/Fishwaldo/rundeck-api-java-client.git
synced 2025-07-09 06:28:44 +00:00
add support for running ad-hoc commands
This commit is contained in:
parent
3512577022
commit
bd9fcca724
9 changed files with 556 additions and 50 deletions
|
@ -17,9 +17,10 @@ import org.rundeck.api.parser.JobParser;
|
|||
import org.rundeck.api.parser.JobsParser;
|
||||
import org.rundeck.api.parser.ProjectParser;
|
||||
import org.rundeck.api.parser.ProjectsParser;
|
||||
import org.rundeck.api.util.ArgsUtil;
|
||||
import org.rundeck.api.util.AssertUtil;
|
||||
import org.rundeck.api.util.NodeFiltersBuilder;
|
||||
import org.rundeck.api.util.OptionsBuilder;
|
||||
import org.rundeck.api.util.ParametersUtil;
|
||||
|
||||
/**
|
||||
* Main entry point to talk to a RunDeck instance
|
||||
|
@ -239,8 +240,9 @@ public class RundeckClient implements Serializable {
|
|||
RundeckApiLoginException, IllegalArgumentException {
|
||||
AssertUtil.notBlank(jobId, "jobId is mandatory to trigger a job !");
|
||||
StringBuilder apiPath = new StringBuilder("/job/").append(jobId).append("/run");
|
||||
if (options != null) {
|
||||
apiPath.append("?argString=").append(ArgsUtil.generateUrlEncodedArgString(options));
|
||||
String argString = ParametersUtil.generateArgString(options);
|
||||
if (StringUtils.isNotBlank(argString)) {
|
||||
apiPath.append("?argString=").append(ParametersUtil.urlEncode(argString));
|
||||
}
|
||||
return new ApiCall(this).get(apiPath.toString(), new ExecutionParser("result/executions/execution"));
|
||||
}
|
||||
|
@ -320,6 +322,150 @@ public class RundeckClient implements Serializable {
|
|||
return execution;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ad-hoc executions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
|
||||
* The command will not be dispatched to nodes, but be executed on the RunDeck server.
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @param command to be executed - mandatory
|
||||
* @return a {@link RundeckExecution} instance for the newly created (and running) execution - 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 or command is blank (null, empty or whitespace)
|
||||
* @see #triggerAdhocCommand(String, String, Properties)
|
||||
*/
|
||||
public RundeckExecution triggerAdhocCommand(String project, String command) throws RundeckApiException,
|
||||
RundeckApiLoginException, IllegalArgumentException {
|
||||
return triggerAdhocCommand(project, command, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
|
||||
* The command will be dispatched to nodes, accordingly to the nodeFilters parameter.
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @param command to be executed - mandatory
|
||||
* @param nodeFilters for selecting nodes on which the command will be executed. See {@link NodeFiltersBuilder}
|
||||
* @return a {@link RundeckExecution} instance for the newly created (and running) execution - 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 or command is blank (null, empty or whitespace)
|
||||
* @see #triggerAdhocCommand(String, String)
|
||||
*/
|
||||
public RundeckExecution triggerAdhocCommand(String project, String command, Properties nodeFilters)
|
||||
throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
|
||||
AssertUtil.notBlank(project, "project is mandatory to trigger an ad-hoc command !");
|
||||
AssertUtil.notBlank(command, "command is mandatory to trigger an ad-hoc command !");
|
||||
StringBuilder apiPath = new StringBuilder("/run/command");
|
||||
apiPath.append("?project=").append(project);
|
||||
apiPath.append("&exec=").append(ParametersUtil.urlEncode(command));
|
||||
String filters = ParametersUtil.generateNodeFiltersString(nodeFilters);
|
||||
if (StringUtils.isNotBlank(filters)) {
|
||||
apiPath.append("&").append(filters);
|
||||
}
|
||||
RundeckExecution execution = new ApiCall(this).get(apiPath.toString(), new ExecutionParser("result/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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
|
||||
* server at regular interval (every 5 seconds) to know if the execution is finished (or aborted) or is still
|
||||
* running. The command will not be dispatched to nodes, but be executed on the RunDeck server.
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @param command to be executed - mandatory
|
||||
* @return a {@link RundeckExecution} instance for the (finished/aborted) execution - 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 or command is blank (null, empty or whitespace)
|
||||
*/
|
||||
public RundeckExecution runAdhocCommand(String project, String command) throws RundeckApiException,
|
||||
RundeckApiLoginException, IllegalArgumentException {
|
||||
return runAdhocCommand(project, command, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
|
||||
* server at regular interval (configured by the poolingInterval/poolingUnit couple) to know if the execution is
|
||||
* finished (or aborted) or is still running. The command will not be dispatched to nodes, but be executed on the
|
||||
* RunDeck server.
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @param command to be executed - mandatory
|
||||
* @param poolingInterval for checking the status of the execution. Must be > 0.
|
||||
* @param poolingUnit unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
|
||||
* @return a {@link RundeckExecution} instance for the (finished/aborted) execution - 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 or command is blank (null, empty or whitespace)
|
||||
*/
|
||||
public RundeckExecution runAdhocCommand(String project, String command, long poolingInterval, TimeUnit poolingUnit)
|
||||
throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
|
||||
return runAdhocCommand(project, command, null, poolingInterval, poolingUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
|
||||
* server at regular interval (every 5 seconds) to know if the execution is finished (or aborted) or is still
|
||||
* running. The command will be dispatched to nodes, accordingly to the nodeFilters parameter.
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @param command to be executed - mandatory
|
||||
* @param nodeFilters for selecting nodes on which the command will be executed. See {@link NodeFiltersBuilder}
|
||||
* @return a {@link RundeckExecution} instance for the (finished/aborted) execution - 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 or command is blank (null, empty or whitespace)
|
||||
*/
|
||||
public RundeckExecution runAdhocCommand(String project, String command, Properties nodeFilters)
|
||||
throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
|
||||
return runAdhocCommand(project, command, nodeFilters, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
|
||||
* server at regular interval (configured by the poolingInterval/poolingUnit couple) to know if the execution is
|
||||
* finished (or aborted) or is still running. The command will be dispatched to nodes, accordingly to the
|
||||
* nodeFilters parameter.
|
||||
*
|
||||
* @param project name of the project - mandatory
|
||||
* @param command to be executed - mandatory
|
||||
* @param nodeFilters for selecting nodes on which the command will be executed. See {@link NodeFiltersBuilder}
|
||||
* @param poolingInterval for checking the status of the execution. Must be > 0.
|
||||
* @param poolingUnit unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
|
||||
* @return a {@link RundeckExecution} instance for the (finished/aborted) execution - 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 or command is blank (null, empty or whitespace)
|
||||
*/
|
||||
public RundeckExecution runAdhocCommand(String project, String command, Properties nodeFilters,
|
||||
long poolingInterval, TimeUnit poolingUnit) throws RundeckApiException, RundeckApiLoginException,
|
||||
IllegalArgumentException {
|
||||
if (poolingInterval <= 0) {
|
||||
poolingInterval = 5;
|
||||
poolingUnit = TimeUnit.SECONDS;
|
||||
}
|
||||
if (poolingUnit == null) {
|
||||
poolingUnit = TimeUnit.SECONDS;
|
||||
}
|
||||
|
||||
RundeckExecution execution = triggerAdhocCommand(project, command, nodeFilters);
|
||||
while (ExecutionStatus.RUNNING.equals(execution.getStatus())) {
|
||||
try {
|
||||
Thread.sleep(poolingUnit.toMillis(poolingInterval));
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
execution = getExecution(execution.getId());
|
||||
}
|
||||
return execution;
|
||||
}
|
||||
|
||||
/*
|
||||
* Executions
|
||||
*/
|
||||
|
|
|
@ -36,11 +36,17 @@ public class ExecutionParser implements NodeParser<RundeckExecution> {
|
|||
|
||||
execution.setId(Long.valueOf(execNode.valueOf("@id")));
|
||||
execution.setUrl(StringUtils.trimToNull(execNode.valueOf("@href")));
|
||||
try {
|
||||
execution.setStatus(ExecutionStatus.valueOf(StringUtils.upperCase(execNode.valueOf("@status"))));
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
execution.setDescription(StringUtils.trimToNull(execNode.valueOf("description")));
|
||||
execution.setStartedBy(StringUtils.trimToNull(execNode.valueOf("user")));
|
||||
execution.setStartedAt(new Date(Long.valueOf(execNode.valueOf("date-started/@unixtime"))));
|
||||
execution.setAbortedBy(StringUtils.trimToNull(execNode.valueOf("abortedby")));
|
||||
String startedAt = StringUtils.trimToNull(execNode.valueOf("date-started/@unixtime"));
|
||||
if (startedAt != null) {
|
||||
execution.setStartedAt(new Date(Long.valueOf(startedAt)));
|
||||
}
|
||||
String endedAt = StringUtils.trimToNull(execNode.valueOf("date-ended/@unixtime"));
|
||||
if (endedAt != null) {
|
||||
execution.setEndedAt(new Date(Long.valueOf(endedAt)));
|
||||
|
|
274
src/main/java/org/rundeck/api/util/NodeFiltersBuilder.java
Normal file
274
src/main/java/org/rundeck/api/util/NodeFiltersBuilder.java
Normal file
|
@ -0,0 +1,274 @@
|
|||
package org.rundeck.api.util;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* Builder for node filters
|
||||
*
|
||||
* @author Vincent Behar
|
||||
*/
|
||||
public class NodeFiltersBuilder {
|
||||
|
||||
private final Properties filters;
|
||||
|
||||
/**
|
||||
* Build a new instance. At the end, use {@link #toProperties()}.
|
||||
*/
|
||||
public NodeFiltersBuilder() {
|
||||
filters = new Properties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given hostname
|
||||
*
|
||||
* @param hostname
|
||||
* @return this, for method chaining
|
||||
* @see #excludeHostname(String)
|
||||
*/
|
||||
public NodeFiltersBuilder hostname(String hostname) {
|
||||
if (StringUtils.isNotBlank(hostname)) {
|
||||
filters.put("hostname", hostname);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given type
|
||||
*
|
||||
* @param type
|
||||
* @return this, for method chaining
|
||||
* @see #excludeType(String)
|
||||
*/
|
||||
public NodeFiltersBuilder type(String type) {
|
||||
if (StringUtils.isNotBlank(type)) {
|
||||
filters.put("type", type);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given tags
|
||||
*
|
||||
* @param tags
|
||||
* @return this, for method chaining
|
||||
* @see #excludeTags(String)
|
||||
*/
|
||||
public NodeFiltersBuilder tags(String tags) {
|
||||
if (StringUtils.isNotBlank(tags)) {
|
||||
filters.put("tags", tags);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given name
|
||||
*
|
||||
* @param name
|
||||
* @return this, for method chaining
|
||||
* @see #excludeName(String)
|
||||
*/
|
||||
public NodeFiltersBuilder name(String name) {
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
filters.put("name", name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given OS-name
|
||||
*
|
||||
* @param osName
|
||||
* @return this, for method chaining
|
||||
* @see #excludeOsName(String)
|
||||
*/
|
||||
public NodeFiltersBuilder osName(String osName) {
|
||||
if (StringUtils.isNotBlank(osName)) {
|
||||
filters.put("os-name", osName);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given OS-family
|
||||
*
|
||||
* @param osFamily
|
||||
* @return this, for method chaining
|
||||
* @see #excludeOsFamily(String)
|
||||
*/
|
||||
public NodeFiltersBuilder osFamily(String osFamily) {
|
||||
if (StringUtils.isNotBlank(osFamily)) {
|
||||
filters.put("os-family", osFamily);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given OS-arch
|
||||
*
|
||||
* @param osArch
|
||||
* @return this, for method chaining
|
||||
* @see #excludeOsArch(String)
|
||||
*/
|
||||
public NodeFiltersBuilder osArch(String osArch) {
|
||||
if (StringUtils.isNotBlank(osArch)) {
|
||||
filters.put("os-arch", osArch);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include nodes matching the given OS-version
|
||||
*
|
||||
* @param osVersion
|
||||
* @return this, for method chaining
|
||||
* @see #excludeOsVersion(String)
|
||||
*/
|
||||
public NodeFiltersBuilder osVersion(String osVersion) {
|
||||
if (StringUtils.isNotBlank(osVersion)) {
|
||||
filters.put("os-version", osVersion);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given hostname
|
||||
*
|
||||
* @param hostname
|
||||
* @return this, for method chaining
|
||||
* @see #hostname(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeHostname(String hostname) {
|
||||
if (StringUtils.isNotBlank(hostname)) {
|
||||
filters.put("exclude-hostname", hostname);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given type
|
||||
*
|
||||
* @param type
|
||||
* @return this, for method chaining
|
||||
* @see #type(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeType(String type) {
|
||||
if (StringUtils.isNotBlank(type)) {
|
||||
filters.put("exclude-type", type);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given tags
|
||||
*
|
||||
* @param tags
|
||||
* @return this, for method chaining
|
||||
* @see #tags(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeTags(String tags) {
|
||||
if (StringUtils.isNotBlank(tags)) {
|
||||
filters.put("exclude-tags", tags);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given name
|
||||
*
|
||||
* @param name
|
||||
* @return this, for method chaining
|
||||
* @see #name(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeName(String name) {
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
filters.put("exclude-name", name);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given OS-name
|
||||
*
|
||||
* @param osName
|
||||
* @return this, for method chaining
|
||||
* @see #osName(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeOsName(String osName) {
|
||||
if (StringUtils.isNotBlank(osName)) {
|
||||
filters.put("exclude-os-name", osName);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given OS-family
|
||||
*
|
||||
* @param osFamily
|
||||
* @return this, for method chaining
|
||||
* @see #osFamily(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeOsFamily(String osFamily) {
|
||||
if (StringUtils.isNotBlank(osFamily)) {
|
||||
filters.put("exclude-os-family", osFamily);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given OS-arch
|
||||
*
|
||||
* @param osArch
|
||||
* @return this, for method chaining
|
||||
* @see #osArch(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeOsArch(String osArch) {
|
||||
if (StringUtils.isNotBlank(osArch)) {
|
||||
filters.put("exclude-os-arch", osArch);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude nodes matching the given OS-version
|
||||
*
|
||||
* @param osVersion
|
||||
* @return this, for method chaining
|
||||
* @see #osVersion(String)
|
||||
* @see #excludePrecedence(boolean)
|
||||
*/
|
||||
public NodeFiltersBuilder excludeOsVersion(String osVersion) {
|
||||
if (StringUtils.isNotBlank(osVersion)) {
|
||||
filters.put("exclude-os-version", osVersion);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether exclusion filters take precedence (default to yes).
|
||||
*
|
||||
* @param excludePrecedence
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public NodeFiltersBuilder excludePrecedence(boolean excludePrecedence) {
|
||||
filters.put("exclude-precedence", Boolean.toString(excludePrecedence));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link Properties} instance
|
||||
*/
|
||||
public Properties toProperties() {
|
||||
Properties filters = new Properties();
|
||||
filters.putAll(this.filters);
|
||||
return filters;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,33 +2,31 @@ package org.rundeck.api.util;
|
|||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Map.Entry;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* Utility class for RunDeck arguments
|
||||
* Utility class for API parameters that should be passed in URLs.
|
||||
*
|
||||
* @author Vincent Behar
|
||||
*/
|
||||
public class ArgsUtil {
|
||||
public class ParametersUtil {
|
||||
|
||||
/**
|
||||
* Generates and url-encode a RunDeck "argString" representing the given options. Format of the argString is
|
||||
* <code>"-key1 value1 -key2 'value 2 with spaces'"</code>
|
||||
* URL-encode the given string
|
||||
*
|
||||
* @param options to be converted
|
||||
* @return an url-encoded string. null if options is null, empty if there are no valid options.
|
||||
* @see #generateArgString(Properties)
|
||||
* @param input string to be encoded
|
||||
* @return an url-encoded string
|
||||
*/
|
||||
public static String generateUrlEncodedArgString(Properties options) {
|
||||
String argString = generateArgString(options);
|
||||
if (StringUtils.isBlank(argString)) {
|
||||
return argString;
|
||||
public static String urlEncode(String input) {
|
||||
if (StringUtils.isBlank(input)) {
|
||||
return input;
|
||||
}
|
||||
|
||||
try {
|
||||
return URLEncoder.encode(argString, "UTF-8");
|
||||
return URLEncoder.encode(input, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -36,11 +34,10 @@ public class ArgsUtil {
|
|||
|
||||
/**
|
||||
* Generates a RunDeck "argString" representing the given options. Format of the argString is
|
||||
* <code>"-key1 value1 -key2 'value 2 with spaces'"</code>
|
||||
* <code>"-key1 value1 -key2 'value 2 with spaces'"</code>. You might want to url-encode this string...
|
||||
*
|
||||
* @param options to be converted
|
||||
* @return a string. null if options is null, empty if there are no valid options.
|
||||
* @see #generateUrlEncodedArgString(Properties)
|
||||
*/
|
||||
public static String generateArgString(Properties options) {
|
||||
if (options == null) {
|
||||
|
@ -69,4 +66,32 @@ public class ArgsUtil {
|
|||
return argString.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an url-encoded string representing the given nodeFilters. Format of the string is
|
||||
* <code>"filter1=value1&filter2=value2"</code>.
|
||||
*
|
||||
* @param nodeFilters to be converted
|
||||
* @return an url-encoded string. null if nodeFilters is null, empty if there are no valid filters.
|
||||
*/
|
||||
public static String generateNodeFiltersString(Properties nodeFilters) {
|
||||
if (nodeFilters == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> filters = new ArrayList<String>();
|
||||
for (Entry<Object, Object> filter : nodeFilters.entrySet()) {
|
||||
String key = String.valueOf(filter.getKey());
|
||||
String value = String.valueOf(filter.getValue());
|
||||
|
||||
if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(value)) {
|
||||
try {
|
||||
filters.add(URLEncoder.encode(key, "UTF-8") + "=" + URLEncoder.encode(value, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.join(filters, "&");
|
||||
}
|
||||
|
||||
}
|
|
@ -64,4 +64,44 @@ public class ExecutionParserTest {
|
|||
Assert.assertEquals("list files", job.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseAdhocNode() throws Exception {
|
||||
InputStream input = getClass().getResourceAsStream("execution-adhoc.xml");
|
||||
Document document = ParserHelper.loadDocument(input);
|
||||
|
||||
RundeckExecution execution = new ExecutionParser("result/executions/execution").parseNode(document);
|
||||
RundeckJob job = execution.getJob();
|
||||
|
||||
Assert.assertEquals(new Long(1), execution.getId());
|
||||
Assert.assertEquals("http://localhost:4440/execution/follow/1", execution.getUrl());
|
||||
Assert.assertEquals(ExecutionStatus.SUCCEEDED, execution.getStatus());
|
||||
Assert.assertEquals("admin", execution.getStartedBy());
|
||||
Assert.assertEquals(new Date(1309857539137L), execution.getStartedAt());
|
||||
Assert.assertEquals(new Date(1309857539606L), execution.getEndedAt());
|
||||
Assert.assertEquals(null, execution.getAbortedBy());
|
||||
Assert.assertEquals("w", execution.getDescription());
|
||||
|
||||
Assert.assertNull(job);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMinimalistNode() throws Exception {
|
||||
InputStream input = getClass().getResourceAsStream("execution-minimalist.xml");
|
||||
Document document = ParserHelper.loadDocument(input);
|
||||
|
||||
RundeckExecution execution = new ExecutionParser("result/execution").parseNode(document);
|
||||
RundeckJob job = execution.getJob();
|
||||
|
||||
Assert.assertEquals(new Long(1), execution.getId());
|
||||
Assert.assertNull(execution.getUrl());
|
||||
Assert.assertNull(execution.getStatus());
|
||||
Assert.assertNull(execution.getStartedBy());
|
||||
Assert.assertNull(execution.getStartedAt());
|
||||
Assert.assertNull(execution.getEndedAt());
|
||||
Assert.assertNull(execution.getAbortedBy());
|
||||
Assert.assertNull(execution.getDescription());
|
||||
|
||||
Assert.assertNull(job);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package org.rundeck.api.util;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test the {@link ArgsUtil}
|
||||
*
|
||||
* @author Vincent Behar
|
||||
*/
|
||||
public class ArgsUtilTest {
|
||||
|
||||
@Test
|
||||
public void generateArgString() throws Exception {
|
||||
Assert.assertNull(ArgsUtil.generateArgString(null));
|
||||
Assert.assertEquals("", ArgsUtil.generateArgString(new Properties()));
|
||||
|
||||
Properties options = new Properties();
|
||||
options.put("key1", "value1");
|
||||
options.put("key2", "value 2 with spaces");
|
||||
String argString = ArgsUtil.generateArgString(options);
|
||||
if (argString.startsWith("-key1")) {
|
||||
Assert.assertEquals("-key1 value1 -key2 'value 2 with spaces'", argString);
|
||||
} else {
|
||||
Assert.assertEquals("-key2 'value 2 with spaces' -key1 value1", argString);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
43
src/test/java/org/rundeck/api/util/ParametersUtilTest.java
Normal file
43
src/test/java/org/rundeck/api/util/ParametersUtilTest.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package org.rundeck.api.util;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test the {@link ParametersUtil}
|
||||
*
|
||||
* @author Vincent Behar
|
||||
*/
|
||||
public class ParametersUtilTest {
|
||||
|
||||
@Test
|
||||
public void generateArgString() throws Exception {
|
||||
Assert.assertNull(ParametersUtil.generateArgString(null));
|
||||
Assert.assertEquals("", ParametersUtil.generateArgString(new Properties()));
|
||||
|
||||
Properties options = new Properties();
|
||||
options.put("key1", "value1");
|
||||
options.put("key2", "value 2 with spaces");
|
||||
String argString = ParametersUtil.generateArgString(options);
|
||||
if (argString.startsWith("-key1")) {
|
||||
Assert.assertEquals("-key1 value1 -key2 'value 2 with spaces'", argString);
|
||||
} else {
|
||||
Assert.assertEquals("-key2 'value 2 with spaces' -key1 value1", argString);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateNodeFiltersString() throws Exception {
|
||||
Assert.assertNull(ParametersUtil.generateNodeFiltersString(null));
|
||||
Assert.assertEquals("", ParametersUtil.generateNodeFiltersString(new Properties()));
|
||||
|
||||
Properties filters = new Properties();
|
||||
filters.put("tags", "appserv+front");
|
||||
filters.put("exclude-tags", "qa,dev");
|
||||
filters.put("os-family", "unix");
|
||||
String result = ParametersUtil.generateNodeFiltersString(filters);
|
||||
Assert.assertEquals("os-family=unix&exclude-tags=qa%2Cdev&tags=appserv%2Bfront", result);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<result success='true' apiversion='1'><executions count='1'><execution id='1' href='http://localhost:4440/execution/follow/1' status='succeeded'><user>admin</user><date-started unixtime='1309857539137'>2011-07-05T09:18:59Z</date-started><date-ended unixtime='1309857539606'>2011-07-05T09:18:59Z</date-ended><description>w</description></execution></executions></result>
|
|
@ -0,0 +1 @@
|
|||
<result success='true' apiversion='1'><success><message>Immediate execution scheduled (1)</message></success><execution id='1'/></result>
|
Loading…
Add table
Add a link
Reference in a new issue