List all jobs that belongs to the given project
@@ -206,6 +242,9 @@ Method in class org.rundeck.api.getProjects() -
Method in class org.rundeck.api.RundeckClient
Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
@@ -430,6 +538,21 @@ Method in class org.rundeck.api.RundeckClient
Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
end of the job execution)
+
runAdhocCommand(String project,
+ String command,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
runJob(String jobId,
+ Properties options)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
runJob(String jobId,
+ Properties options,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
runJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
runJob(String jobId,
+ Properties options,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
+
+
+
void
testCredentials()
@@ -304,6 +412,25 @@ Main entry point to talk to a RunDeck instance
triggerAdhocCommand(String project,
+ String command)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
triggerAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
triggerJob(String jobId)
@@ -316,6 +443,17 @@ Main entry point to talk to a RunDeck instance
triggerJob(String jobId,
Properties options)
+
+ Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
+ end of the job execution)
triggerJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
end of the job execution)
Run a RunDeck job (identified by the given ID), 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.
+
+
+
+
+
+
Parameters:
jobId - identifier of the job - mandatory
+
Returns:
a RundeckExecution instance for the (finished/aborted) execution - won't be null
+
Throws:
+
RundeckApiException - in case of error when calling the API (non-existent job with this ID)
+
Run a RunDeck job (identified by the given ID), 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.
+
Run a RunDeck job (identified by the given ID), 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.
+
Run a RunDeck job (identified by the given ID), 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.
+
Run a RunDeck job (identified by the given ID), 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.
+
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.
+
+
+
+
+
+
Parameters:
project - name of the project - mandatory
command - to be executed - mandatory
+
Returns:
a 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)
+
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.
+
+
+
+
+
+
Parameters:
project - name of the project - mandatory
command - to be executed - mandatory
nodeFilters - for selecting nodes on which the command will be executed. See NodeFiltersBuilder
+
Returns:
a 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)
+
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.
+
+
+
+
+
+
Parameters:
project - name of the project - mandatory
command - to be executed - mandatory
+
Returns:
a 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)
+
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.
+
+
+
+
+
+
Parameters:
project - name of the project - mandatory
command - to be executed - mandatory
poolingInterval - for checking the status of the execution. Must be > 0.
poolingUnit - unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
+
Returns:
a 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)
+
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.
+
+
+
+
+
+
Parameters:
project - name of the project - mandatory
command - to be executed - mandatory
nodeFilters - for selecting nodes on which the command will be executed. See NodeFiltersBuilder
+
Returns:
a 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)
+
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.
+
+
+
+
+
+
Parameters:
project - name of the project - mandatory
command - to be executed - mandatory
nodeFilters - for selecting nodes on which the command will be executed. See NodeFiltersBuilder
poolingInterval - for checking the status of the execution. Must be > 0.
poolingUnit - unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
+
Returns:
a 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)
+
RundeckClient.runAdhocCommand(String project,
+ String command)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
+
+
+
void
RundeckClient.testCredentials()
@@ -191,6 +299,25 @@ Uses of
RundeckClient.triggerAdhocCommand(String project,
+ String command)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
RundeckClient.triggerAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
RundeckClient.triggerJob(String jobId)
@@ -203,6 +330,17 @@ Uses of triggerJob(String jobId,
Properties options)
+
+ Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
+ end of the job execution)
RundeckClient.triggerJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
end of the job execution)
diff --git a/apidocs/org/rundeck/api/class-use/RundeckApiException.html b/apidocs/org/rundeck/api/class-use/RundeckApiException.html
index 26b477f..bbb79d4 100644
--- a/apidocs/org/rundeck/api/class-use/RundeckApiException.html
+++ b/apidocs/org/rundeck/api/class-use/RundeckApiException.html
@@ -2,13 +2,13 @@
-
+
Uses of Class org.rundeck.api.RundeckApiException (RunDeck API - Java Client 1.0-SNAPSHOT API)
-
+
@@ -168,6 +168,14 @@ Uses of
RundeckClient.runAdhocCommand(String project,
+ String command)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.triggerAdhocCommand(String project,
+ String command)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
RundeckClient.triggerAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
RundeckClient.triggerJob(String jobId)
@@ -223,6 +350,17 @@ Uses of triggerJob(String jobId,
Properties options)
+
+ Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
+ end of the job execution)
RundeckClient.triggerJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
end of the job execution)
diff --git a/apidocs/org/rundeck/api/class-use/RundeckClient.html b/apidocs/org/rundeck/api/class-use/RundeckClient.html
index 8d7f9f3..9a13f37 100644
--- a/apidocs/org/rundeck/api/class-use/RundeckClient.html
+++ b/apidocs/org/rundeck/api/class-use/RundeckClient.html
@@ -2,13 +2,13 @@
-
+
Uses of Class org.rundeck.api.RundeckClient (RunDeck API - Java Client 1.0-SNAPSHOT API)
-
+
diff --git a/apidocs/org/rundeck/api/domain/RundeckExecution.ExecutionStatus.html b/apidocs/org/rundeck/api/domain/RundeckExecution.ExecutionStatus.html
index 017f4f1..4048564 100644
--- a/apidocs/org/rundeck/api/domain/RundeckExecution.ExecutionStatus.html
+++ b/apidocs/org/rundeck/api/domain/RundeckExecution.ExecutionStatus.html
@@ -2,13 +2,13 @@
-
+
RundeckExecution.ExecutionStatus (RunDeck API - Java Client 1.0-SNAPSHOT API)
-
+
diff --git a/apidocs/org/rundeck/api/domain/RundeckExecution.html b/apidocs/org/rundeck/api/domain/RundeckExecution.html
index 9c54970..a6391b7 100644
--- a/apidocs/org/rundeck/api/domain/RundeckExecution.html
+++ b/apidocs/org/rundeck/api/domain/RundeckExecution.html
@@ -2,13 +2,13 @@
-
+
RundeckExecution (RunDeck API - Java Client 1.0-SNAPSHOT API)
-
+
@@ -180,6 +180,22 @@ Represents a RunDeck execution, usually triggered by an API call. An execution c
String
RundeckClient.runAdhocCommand(String project,
+ String command)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runAdhocCommand(String project,
+ String command,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run an ad-hoc command, and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.runJob(String jobId,
+ Properties options,
+ Properties nodeFilters,
+ long poolingInterval,
+ TimeUnit poolingUnit)
+
+
+ Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
RundeckClient.triggerAdhocCommand(String project,
+ String command)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
RundeckClient.triggerAdhocCommand(String project,
+ String command,
+ Properties nodeFilters)
+
+
+ Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
RundeckClient.triggerJob(String jobId)
@@ -138,6 +249,17 @@ Uses of RundeckClient.triggerJob(String jobId,
Properties options)
+
+ Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
+ end of the job execution)
RundeckClient.triggerJob(String jobId,
+ Properties options,
+ Properties nodeFilters)
+
Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
end of the job execution)
Generates a RunDeck "argString" representing the given options. Format of the argString is
+ "-key1 value1 -key2 'value 2 with spaces'". You might want to url-encode this string...
+
+
+
Parameters:
options - to be converted
+
Returns:
a string. null if options is null, empty if there are no valid options.
Description: The codec package contains simple encoder and decoders for
various formats such as Base64 and Hexadecimal. In addition to these
widely used encoders and decoders, the codec package also maintains a
- collection of phonetic encoding utilities.
Description: Commons Lang, a package of Java utility classes for the
classes that are in java.lang's hierarchy, or are considered to be so
- standard as to justify existence in java.lang.
Project License: No project license is defined for this project.
xml-apis:xml-apis:jar:1.0.b2 (compile)
XML Commons External Components XML APIs
Description: xml-commons provides an Apache-hosted set of DOM, SAX, and
JAXP interfaces for use in other xml-based projects. Our hope is that we
can standardize on both a common version and packaging scheme for these
critical XML standards interfaces to make the lives of both our developers
and users easier. The External Components portion of xml-commons contains
interfaces that are defined by external standards organizations. For DOM,
that's the W3C; for SAX it's David Megginson and sax.sourceforge.net; for
- JAXP it's Sun.
Description: There is currently no description associated with this project.
Project License: No project license is defined for this project.
xerces:xercesImpl:jar:2.6.2 (compile)
Unnamed - xerces:xercesImpl:jar:2.6.2
Description: There is currently no description associated with this project.
Project License: No project license is defined for this project.
xalan:xalan:jar:2.6.0 (compile)
Unnamed - xalan:xalan:jar:2.6.0
Description: There is currently no description associated with this project.
Project License: No project license is defined for this project.
xml-apis:xml-apis:jar:1.0.b2 (compile)
XML Commons External Components XML APIs
Description: xml-commons provides an Apache-hosted set of DOM, SAX, and
JAXP interfaces for use in other xml-based projects. Our hope is that we
can standardize on both a common version and packaging scheme for these
critical XML standards interfaces to make the lives of both our developers
and users easier. The External Components portion of xml-commons contains
interfaces that are defined by external standards organizations. For DOM,
that's the W3C; for SAX it's David Megginson and sax.sourceforge.net; for
- JAXP it's Sun.
The Apache Software License, Version 2.0: Commons Codec, Commons Lang, Commons Logging, RunDeck API - Java Client, XML Commons External Components XML APIs
The Apache Software License, Version 2.0: Commons Codec, Commons Lang, Commons Logging, RunDeck API - Java Client, XML Commons External Components XML APIs
Here are some examples of what you can do with this lib and a few lines of Groovy. We can use Grape to download the lib (and its dependencies) from the main maven repository, so you don't have to install anything manually (except Groovy, of course).
Note that the lib is NOT in the main maven repository for the moment... but hopefully it should be pretty soon !
Running a job (from its name, group and project)
Save the following script in a file named "rundeck.groovy", and execute it with "groovy rundeck.groovy". Feeling Groovy ? ;-)
Here are some examples of what you can do with this lib and a few lines of Groovy.
We can use Grape to download the lib (and its dependencies) from the Maven Central Repository, so you don't have to install anything manually (except Groovy, of course).
Note that the lib is NOT in the Maven Central Repository for the moment... but hopefully it should be pretty soon ! You can still download it manually.
Basic usage
Save the following script in a file named "rundeck.groovy", and execute it with "groovy rundeck.groovy". Feeling Groovy ? ;-)
// we use Grape (Ivy) to download the lib (and its dependencies) from Maven Central Repository
+@Grab(group='org.rundeck', module='rundeck-api-java-client', version='1.0-SNAPSHOT')
import org.rundeck.api.RundeckClient
rundeck = new RundeckClient("http://localhost:4440", "admin", "admin")
-job = rundeck.findJob("my-project", "main-group/sub-group", "job-name")
-println "Running job : ${job}"
+println "All RunDeck projects : ${rundeck.projects}"
+println "All RunDeck jobs : ${rundeck.jobs}"
+
You can also download the lib and all its dependencies in 1 big jar file, and add it to your classpath before running your script : save the following script in a file named "rundeck.groovy", and execute it with "groovy -cp /path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar rundeck.groovy".
import org.rundeck.api.RundeckClient
+rundeck = new RundeckClient("http://localhost:4440", "admin", "admin")
+
+println "All RunDeck projects : ${rundeck.projects}"
+println "All RunDeck jobs : ${rundeck.jobs}"
+
Running a job
import org.rundeck.api.RundeckClient
+rundeck = new RundeckClient("http://localhost:4440", "admin", "admin")
+
+// find a job from its name, group and project
+job = rundeck.findJob("my-project", "main-group/sub-group", "job-name")
+println "Found job with ID : ${job.id}"
+
+// trigger a simple job with no options
execution = rundeck.triggerJob(job.id)
-println "Follow the execution at : ${execution.url}"
And more...
See the API documentation of the RundeckClient class for more interactions with your RunDeck instance...
+println "Execution started, you can follow it at the URL : ${execution.url}"
+
+// or with options...
+execution = rundeck.triggerJob("job-id", new Properties(option1: "value one", option2: "value two"))
+
+// you can also override the nodes on which the job should execute
+execution = rundeck.triggerJob("job-id", new Properties(opt: "value"), new Properties(tags: "prod+appserv"))
+
+// last one : you can run a job and wait until its execution is finished :
+execution = rundeck.runJob("job-id")
+println "Execution finished ! Status : ${execution.status}, duration (in seconds) : ${execution.durationInSeconds}"
+
Running an ad-hoc command
import org.rundeck.api.RundeckClient
+rundeck = new RundeckClient("http://localhost:4440", "admin", "admin")
+
+// trigger the execution of the "uptime" command on the RunDeck server
+execution = rundeck.triggerAdhocCommand("my-project", "uptime")
+
+// run the "uptime" command on all unix nodes
+execution = rundeck.runAdhocCommand("my-project", "uptime", new Properties(os-family: "unix"))
+
And more...
See the API documentation of the RundeckClient class for more interactions with your RunDeck instance...
@@ -112,7 +157,7 @@ println "Follow the execution at : ${execution.url}"
A Java librairie that maps the RunDeck HTTP REST API. RunDeck is an open-source tool for automating tasks on multiple nodes, with a CLI, a web-based interface and an HTTP REST API. You can read more about its API on the RunDeck User Manual.
This librairie has been extracted from the Jenkins RunDeck plugin, so for the moment it is still incomplete (not all the RunDeck API is mapped). My goal is to have a complete mapping of the RunDeck API, and to publish the librairie on the main maven repository, so that it can easily be used by Java (Maven) and Groovy (Grape) developers.
What can I do with it ?
Use it in a Java application. A good example would be the Jenkins RunDeck plugin, that needs to trigger RunDeck jobs from within the Jenkins continuous-integration server.
Use it to write Groovy or JRuby scripts, for example if you want to automate the execution of RunDeck jobs based on external events.
A Java librairie that maps the RunDeck HTTP REST API. RunDeck is an open-source tool for automating tasks on multiple nodes, with a CLI, a web-based interface and an HTTP REST API. You can read more about its API on the RunDeck User Manual.
This librairie has been extracted from the Jenkins RunDeck plugin, so for the moment it is still incomplete (not all the RunDeck API is mapped). My goal is to have a complete mapping of the RunDeck API, and to publish the librairie on the Maven Central Repository, so that it can easily be used by Java (Maven) and Groovy (Grape) developers.
What can I do with it ?
Use it to write scripts (in Groovy, JRuby or Jython), for example if you want to automate the execution of RunDeck jobs based on external events.
Use it in a Java application. A good example would be the Jenkins RunDeck plugin, that needs to trigger RunDeck jobs from within the Jenkins continuous-integration server.
Here are some examples of what you can do with this lib and a few lines of Ruby (for the rubyist that don't fear running on the JVM !). You will have to download the lib (the .jar file) to use it...
Running a job (from its name, group and project)
Save the following script in a file named "rundeck.rb", and execute it with "jruby rundeck.rb".
require 'java'
+
Using the RunDeck API from JRuby scripts
Here are some examples of what you can do with this lib and a few lines of Ruby (for the rubyist that don't fear running on the JVM !)
You will have to download the lib (the .jar file) to use it...
Basic usage
Save the following script in a file named "rundeck.rb", and execute it with "jruby rundeck.rb".
require 'java'
require '/path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar'
-java_import org.rundeck.api.RundeckClient
+import org.rundeck.api.RundeckClient
rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin")
+puts "All RunDeck projects : #{rundeck.projects}"
+puts "All RunDeck jobs : #{rundeck.jobs}"
+
You can also add the librairie to the classpath : save the following script in a file named "rundeck.rb", and execute it with "jruby -rjava -J-cp /path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar rundeck.rb".
import org.rundeck.api.RundeckClient
+
+rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin")
+
+puts "All RunDeck projects : #{rundeck.projects}"
+puts "All RunDeck jobs : #{rundeck.jobs}"
+
Running a job
import org.rundeck.api.RundeckClient
+import org.rundeck.api.util.OptionsBuilder
+import org.rundeck.api.util.NodeFiltersBuilder
+
+rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin")
+
+// find a job from its name, group and project
job = rundeck.findJob("my-project", "main-group/sub-group", "job-name")
-puts "Running job : #{job}"
+puts "Found job with ID : #{job.id}"
+// trigger a simple job with no options
execution = rundeck.triggerJob(job.id)
-puts "Follow the execution at : #{execution.url}"
You can also extract all the java-related stuff from the script file : save the following script in a file named "rundeck.rb", and execute it with "jruby -rjava -J-cp /path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar rundeck.rb".
rundeck = org.rundeck.api.RundeckClient.new("http://localhost:4440", "admin", "admin")
+puts "Execution started, you can follow it at the URL : #{execution.url}"
-job = rundeck.findJob("my-project", "main-group/sub-group", "job-name")
-puts "Running job : #{job}"
+// or with options...
+execution = rundeck.triggerJob("job-id", OptionsBuilder.new().addOption("option1", "value one").addOption("option2", "value two").toProperties())
-execution = rundeck.triggerJob(job.id)
-puts "Follow the execution at : #{execution.url}"
And more...
See the API documentation of the RundeckClient class for more interactions with your RunDeck instance...
+// you can also override the nodes on which the job should execute
+execution = rundeck.triggerJob("job-id", OptionsBuilder.new().addOption("opt", "value").toProperties(), NodeFiltersBuilder.new().tags("prod+appserv").toProperties())
+
+// last one : you can run a job and wait until its execution is finished :
+execution = rundeck.runJob("job-id")
+puts "Execution finished ! Status : #{execution.status}, duration (in seconds) : #{execution.durationInSeconds}"
+
Running an ad-hoc command
import org.rundeck.api.RundeckClient
+import org.rundeck.api.util.NodeFiltersBuilder
+
+rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin")
+
+// trigger the execution of the "uptime" command on the RunDeck server
+execution = rundeck.triggerAdhocCommand("my-project", "uptime")
+
+// run the "uptime" command on all unix nodes
+execution = rundeck.runAdhocCommand("my-project", "uptime", NodeFiltersBuilder.new().osFamily("unix").toProperties())
+
And more...
See the API documentation of the RundeckClient class for more interactions with your RunDeck instance...
@@ -119,7 +162,7 @@ puts "Follow the execution at : #{execution.url}"
Here are some examples of what you can do with this lib and a few lines of Python (for the pythonist that don't fear running on the JVM !)
You will have to download the lib (the .jar file) to use it...
Basic usage
Save the following script in a file named "rundeck.py", and execute it with "jython -J-cp /path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar rundeck.py".
from org.rundeck.api import RundeckClient
+from org.rundeck.api.util import OptionsBuilder
+from org.rundeck.api.util import NodeFiltersBuilder
+
+rundeck = RundeckClient("http://localhost:4440", "admin", "admin")
+
+// find a job from its name, group and project
+job = rundeck.findJob("my-project", "main-group/sub-group", "job-name")
+print("Found job with ID : %s" % job.id)
+
+// trigger a simple job with no options
+execution = rundeck.triggerJob(job.id)
+print("Execution started, you can follow it at the URL : %s" % execution.url)
+
+// or with options...
+execution = rundeck.triggerJob("job-id", OptionsBuilder().addOption("option1", "value one").addOption("option2", "value two").toProperties())
+
+// you can also override the nodes on which the job should execute
+execution = rundeck.triggerJob("job-id", OptionsBuilder().addOption("opt", "value").toProperties(), NodeFiltersBuilder().tags("prod+appserv").toProperties())
+
+// last one : you can run a job and wait until its execution is finished :
+execution = rundeck.runJob("job-id")
+print("Execution finished ! Status : %s, duration (in seconds) : %s" % (execution.status, execution.durationInSeconds))
+
Running an ad-hoc command
from org.rundeck.api import RundeckClient
+from org.rundeck.api.util import NodeFiltersBuilder
+
+rundeck = RundeckClient("http://localhost:4440", "admin", "admin")
+
+// trigger the execution of the "uptime" command on the RunDeck server
+execution = rundeck.triggerAdhocCommand("my-project", "uptime")
+
+// run the "uptime" command on all unix nodes
+execution = rundeck.runAdhocCommand("my-project", "uptime", NodeFiltersBuilder().osFamily("unix").toProperties())
+
And more...
See the API documentation of the RundeckClient class for more interactions with your RunDeck instance...
ParserHelper
diff --git a/xref/org/rundeck/api/RundeckClient.html b/xref/org/rundeck/api/RundeckClient.html
index 84038b0..cb82586 100644
--- a/xref/org/rundeck/api/RundeckClient.html
+++ b/xref/org/rundeck/api/RundeckClient.html
@@ -11,315 +11,654 @@
1package org.rundeck.api;
23import java.io.Serializable;
-4import java.util.List;
-5import java.util.Properties;
-6import org.apache.commons.lang.StringUtils;
-7import org.rundeck.api.RundeckApiException.RundeckApiLoginException;
-8import org.rundeck.api.domain.RundeckExecution;
-9import org.rundeck.api.domain.RundeckJob;
-10import org.rundeck.api.domain.RundeckProject;
-11import org.rundeck.api.parser.ExecutionParser;
-12import org.rundeck.api.parser.ExecutionsParser;
-13import org.rundeck.api.parser.JobParser;
-14import org.rundeck.api.parser.JobsParser;
-15import org.rundeck.api.parser.ProjectParser;
-16import org.rundeck.api.parser.ProjectsParser;
-17import org.rundeck.api.util.ArgsUtil;
-18import org.rundeck.api.util.AssertUtil;
-19
-20/**
-21 * Main entry point to talk to a RunDeck instance
-22 *
-23 * @author Vincent Behar
-24 */
-25publicclassRundeckClientimplements Serializable {
-26
-27privatestaticfinallong serialVersionUID = 1L;
-28
-29publicstaticfinaltransientint API_VERSION = 1;
-30
-31publicstaticfinaltransient String API_ENDPOINT = "/api/" + API_VERSION;
-32
-33privatefinal String url;
-34
-35privatefinal String login;
-36
-37privatefinal String password;
-38
-39/**
-40 * Instantiate a new {@link RundeckClient} for the RunDeck instance at the given url
-41 *
-42 * @param url of the RunDeck instance ("http://localhost:4440", "http://rundeck.your-compagny.com/", etc)
-43 * @param login
-44 * @param password
-45 */
-46publicRundeckClient(String url, String login, String password) {
-47super();
-48this.url = url;
-49this.login = login;
-50this.password = password;
-51 }
-52
-53/**
-54 * Try to "ping" the RunDeck instance to see if it is alive
-55 *
-56 * @throws RundeckApiException if the ping fails
-57 */
-58publicvoid ping() throws RundeckApiException {
-59newApiCall(this).ping();
+4import java.util.ArrayList;
+5import java.util.List;
+6import java.util.Properties;
+7import java.util.concurrent.TimeUnit;
+8import org.apache.commons.lang.StringUtils;
+9import org.rundeck.api.RundeckApiException.RundeckApiLoginException;
+10import org.rundeck.api.domain.RundeckExecution;
+11import org.rundeck.api.domain.RundeckJob;
+12import org.rundeck.api.domain.RundeckProject;
+13import org.rundeck.api.domain.RundeckExecution.ExecutionStatus;
+14import org.rundeck.api.parser.ExecutionParser;
+15import org.rundeck.api.parser.ExecutionsParser;
+16import org.rundeck.api.parser.JobParser;
+17import org.rundeck.api.parser.JobsParser;
+18import org.rundeck.api.parser.ProjectParser;
+19import org.rundeck.api.parser.ProjectsParser;
+20import org.rundeck.api.util.AssertUtil;
+21import org.rundeck.api.util.NodeFiltersBuilder;
+22import org.rundeck.api.util.OptionsBuilder;
+23import org.rundeck.api.util.ParametersUtil;
+24
+25/**
+26 * Main entry point to talk to a RunDeck instance
+27 *
+28 * @author Vincent Behar
+29 */
+30publicclassRundeckClientimplements Serializable {
+31
+32privatestaticfinallong serialVersionUID = 1L;
+33
+34publicstaticfinaltransientint API_VERSION = 1;
+35
+36publicstaticfinaltransient String API_ENDPOINT = "/api/" + API_VERSION;
+37
+38privatefinal String url;
+39
+40privatefinal String login;
+41
+42privatefinal String password;
+43
+44/**
+45 * Instantiate a new {@link RundeckClient} for the RunDeck instance at the given url
+46 *
+47 * @param url of the RunDeck instance ("http://localhost:4440", "http://rundeck.your-compagny.com/", etc)
+48 * @param login
+49 * @param password
+50 * @throws IllegalArgumentException if the url, login or password is blank (null, empty or whitespace)
+51 */
+52publicRundeckClient(String url, String login, String password) throws IllegalArgumentException {
+53super();
+54this.url = url;
+55this.login = login;
+56this.password = password;
+57 AssertUtil.notBlank(url, "The RunDeck URL is mandatory !");
+58 AssertUtil.notBlank(login, "The RunDeck login is mandatory !");
+59 AssertUtil.notBlank(password, "The RunDeck password is mandatory !");
60 }
6162/**
-63 * Test your credentials (login/password) on the RunDeck instance
+63 * Try to "ping" the RunDeck instance to see if it is alive64 *
-65 * @throws RundeckApiLoginException if the login fails
+65 * @throws RundeckApiException if the ping fails66 */
-67publicvoid testCredentials() throws RundeckApiLoginException {
-68newApiCall(this).testCredentials();
+67publicvoid ping() throws RundeckApiException {
+68newApiCall(this).ping();
69 }
70
-71/*
-72 * Projects
-73 */
-74
-75/**
-76 * List all projects
-77 *
-78 * @return a {@link List} of {@link RundeckProject} : might be empty, but won't be null
-79 * @throws RundeckApiException in case of error when calling the API
-80 * @throws RundeckApiLoginException if the login failed
-81 */
-82public List<RundeckProject> getProjects() throws RundeckApiException, RundeckApiLoginException {
-83returnnewApiCall(this).get("/projects", newProjectsParser("result/projects/project"));
-84 }
-85
-86/**
-87 * Get the definition of a single project, identified by the given name
-88 *
-89 * @param projectName name of the project - mandatory
-90 * @return a {@link RundeckProject} instance - won't be null
-91 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
-92 * @throws RundeckApiLoginException if the login failed
-93 * @throws IllegalArgumentException if the projectName is blank (null, empty or whitespace)
-94 */
-95publicRundeckProject getProject(String projectName) throws RundeckApiException, RundeckApiLoginException,
-96 IllegalArgumentException {
-97 AssertUtil.notBlank(projectName, "projectName is mandatory to get the details of a project !");
-98returnnewApiCall(this).get("/project/" + projectName, newProjectParser("result/projects/project"));
-99 }
-100
-101/*
-102 * Jobs
-103 */
-104
-105/**
-106 * List all jobs that belongs to the given project
-107 *
-108 * @param project name of the project - mandatory
-109 * @return a {@link List} of {@link RundeckJob} : might be empty, but won't be null
-110 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
-111 * @throws RundeckApiLoginException if the login failed
-112 * @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
-113 * @see #getJobs(String, String, String, String...)
-114 */
-115public List<RundeckJob> getJobs(String project) throws RundeckApiException, RundeckApiLoginException,
-116 IllegalArgumentException {
-117return getJobs(project, null, null, new String[0]);
-118 }
-119
-120/**
-121 * List the jobs that belongs to the given project, and matches the given criteria (jobFilter, groupPath and jobIds)
-122 *
-123 * @param project name of the project - mandatory
-124 * @param jobFilter a filter for the job Name - optional
-125 * @param groupPath a group or partial group path to include all jobs within that group path - optional
-126 * @param jobIds a list of Job IDs to include - optional
-127 * @return a {@link List} of {@link RundeckJob} : might be empty, but won't be null
-128 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
-129 * @throws RundeckApiLoginException if the login failed
-130 * @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
-131 * @see #getJobs(String)
-132 */
-133public List<RundeckJob> getJobs(String project, String jobFilter, String groupPath, String... jobIds)
-134throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
-135 AssertUtil.notBlank(project, "project is mandatory to get all jobs !");
-136 StringBuilder apiPath = new StringBuilder("/jobs");
-137 apiPath.append("?project=").append(project);
-138if (StringUtils.isNotBlank(jobFilter)) {
-139 apiPath.append("&jobFilter=").append(jobFilter);
-140 }
-141if (StringUtils.isNotBlank(groupPath)) {
-142 apiPath.append("&groupPath=").append(groupPath);
-143 }
-144if (jobIds != null && jobIds.length > 0) {
-145 apiPath.append("&idlist=").append(StringUtils.join(jobIds, ","));
-146 }
-147returnnewApiCall(this).get(apiPath.toString(), new JobsParser("result/jobs/job"));
-148 }
-149
-150/**
-151 * Find a job, identified by its project, group and name. Note that the groupPath is optional, as a job does not
-152 * need to belong to a group (either pass null, or an empty string).
-153 *
-154 * @param project name of the project - mandatory
-155 * @param groupPath group to which the job belongs (if it belongs to a group) - optional
-156 * @param name of the job to find - mandatory
-157 * @return a {@link RundeckJob} instance - null if not found
-158 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
-159 * @throws RundeckApiLoginException if the login failed
-160 * @throws IllegalArgumentException if the project or the name is blank (null, empty or whitespace)
-161 */
-162publicRundeckJob findJob(String project, String groupPath, String name) throws RundeckApiException,
-163 RundeckApiLoginException, IllegalArgumentException {
-164 AssertUtil.notBlank(project, "project is mandatory to find a job !");
-165 AssertUtil.notBlank(name, "job name is mandatory to find a job !");
-166 List<RundeckJob> jobs = getJobs(project, name, groupPath, new String[0]);
-167return jobs.isEmpty() ? null : jobs.get(0);
-168 }
-169
-170/**
-171 * Get the definition of a single job, identified by the given ID
-172 *
-173 * @param jobId identifier of the job - mandatory
-174 * @return a {@link RundeckJob} instance - won't be null
-175 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
-176 * @throws RundeckApiLoginException if the login failed
-177 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
-178 */
-179publicRundeckJob getJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
-180 IllegalArgumentException {
-181 AssertUtil.notBlank(jobId, "jobId is mandatory to get the details of a job !");
-182returnnewApiCall(this).get("/job/" + jobId, newJobParser("joblist/job"));
-183 }
-184
-185/**
-186 * Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
-187 * end of the job execution)
-188 *
-189 * @param jobId identifier of the job - mandatory
-190 * @return a {@link RundeckExecution} instance for the newly created (and running) execution - won't be null
-191 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
-192 * @throws RundeckApiLoginException if the login failed
-193 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
-194 * @see #triggerJob(String, Properties)
-195 */
-196publicRundeckExecution triggerJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
-197 IllegalArgumentException {
-198return triggerJob(jobId, null);
-199 }
-200
-201/**
-202 * Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
-203 * end of the job execution)
-204 *
-205 * @param jobId identifier of the job - mandatory
-206 * @param options of the job - optional
-207 * @return a {@link RundeckExecution} instance for the newly created (and running) execution - won't be null
-208 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
-209 * @throws RundeckApiLoginException if the login failed
-210 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
-211 * @see #triggerJob(String)
-212 */
-213publicRundeckExecution triggerJob(String jobId, Properties options) throws RundeckApiException,
-214 RundeckApiLoginException, IllegalArgumentException {
-215 AssertUtil.notBlank(jobId, "jobId is mandatory to trigger a job !");
-216 StringBuilder apiPath = new StringBuilder("/job/").append(jobId).append("/run");
-217if (options != null) {
-218 apiPath.append("?argString=").append(ArgsUtil.generateUrlEncodedArgString(options));
-219 }
-220returnnewApiCall(this).get(apiPath.toString(), new ExecutionParser("result/executions/execution"));
-221 }
-222
-223/*
-224 * Executions
-225 */
-226
-227/**
-228 * Get the executions of the given job
+71/**
+72 * Test your credentials (login/password) on the RunDeck instance
+73 *
+74 * @throws RundeckApiLoginException if the login fails
+75 */
+76publicvoid testCredentials() throws RundeckApiLoginException {
+77newApiCall(this).testCredentials();
+78 }
+79
+80/*
+81 * Projects
+82 */
+83
+84/**
+85 * List all projects
+86 *
+87 * @return a {@link List} of {@link RundeckProject} : might be empty, but won't be null
+88 * @throws RundeckApiException in case of error when calling the API
+89 * @throws RundeckApiLoginException if the login failed
+90 */
+91public List<RundeckProject> getProjects() throws RundeckApiException, RundeckApiLoginException {
+92returnnewApiCall(this).get("/projects", newProjectsParser("result/projects/project"));
+93 }
+94
+95/**
+96 * Get the definition of a single project, identified by the given name
+97 *
+98 * @param projectName name of the project - mandatory
+99 * @return a {@link RundeckProject} instance - won't be null
+100 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+101 * @throws RundeckApiLoginException if the login failed
+102 * @throws IllegalArgumentException if the projectName is blank (null, empty or whitespace)
+103 */
+104publicRundeckProject getProject(String projectName) throws RundeckApiException, RundeckApiLoginException,
+105 IllegalArgumentException {
+106 AssertUtil.notBlank(projectName, "projectName is mandatory to get the details of a project !");
+107returnnewApiCall(this).get("/project/" + projectName, newProjectParser("result/projects/project"));
+108 }
+109
+110/*
+111 * Jobs
+112 */
+113
+114/**
+115 * List all jobs (for all projects)
+116 *
+117 * @return a {@link List} of {@link RundeckJob} : might be empty, but won't be null
+118 * @throws RundeckApiException in case of error when calling the API
+119 * @throws RundeckApiLoginException if the login failed
+120 */
+121public List<RundeckJob> getJobs() throws RundeckApiException, RundeckApiLoginException {
+122 List<RundeckJob> jobs = new ArrayList<RundeckJob>();
+123for (RundeckProject project : getProjects()) {
+124 jobs.addAll(getJobs(project.getName()));
+125 }
+126return jobs;
+127 }
+128
+129/**
+130 * List all jobs that belongs to the given project
+131 *
+132 * @param project name of the project - mandatory
+133 * @return a {@link List} of {@link RundeckJob} : might be empty, but won't be null
+134 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+135 * @throws RundeckApiLoginException if the login failed
+136 * @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
+137 * @see #getJobs(String, String, String, String...)
+138 */
+139public List<RundeckJob> getJobs(String project) throws RundeckApiException, RundeckApiLoginException,
+140 IllegalArgumentException {
+141return getJobs(project, null, null, new String[0]);
+142 }
+143
+144/**
+145 * List the jobs that belongs to the given project, and matches the given criteria (jobFilter, groupPath and jobIds)
+146 *
+147 * @param project name of the project - mandatory
+148 * @param jobFilter a filter for the job Name - optional
+149 * @param groupPath a group or partial group path to include all jobs within that group path - optional
+150 * @param jobIds a list of Job IDs to include - optional
+151 * @return a {@link List} of {@link RundeckJob} : might be empty, but won't be null
+152 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+153 * @throws RundeckApiLoginException if the login failed
+154 * @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
+155 * @see #getJobs(String)
+156 */
+157public List<RundeckJob> getJobs(String project, String jobFilter, String groupPath, String... jobIds)
+158throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+159 AssertUtil.notBlank(project, "project is mandatory to get all jobs !");
+160 StringBuilder apiPath = new StringBuilder("/jobs");
+161 apiPath.append("?project=").append(project);
+162if (StringUtils.isNotBlank(jobFilter)) {
+163 apiPath.append("&jobFilter=").append(jobFilter);
+164 }
+165if (StringUtils.isNotBlank(groupPath)) {
+166 apiPath.append("&groupPath=").append(groupPath);
+167 }
+168if (jobIds != null && jobIds.length > 0) {
+169 apiPath.append("&idlist=").append(StringUtils.join(jobIds, ","));
+170 }
+171returnnewApiCall(this).get(apiPath.toString(), new JobsParser("result/jobs/job"));
+172 }
+173
+174/**
+175 * Find a job, identified by its project, group and name. Note that the groupPath is optional, as a job does not
+176 * need to belong to a group (either pass null, or an empty string).
+177 *
+178 * @param project name of the project - mandatory
+179 * @param groupPath group to which the job belongs (if it belongs to a group) - optional
+180 * @param name of the job to find - mandatory
+181 * @return a {@link RundeckJob} instance - null if not found
+182 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+183 * @throws RundeckApiLoginException if the login failed
+184 * @throws IllegalArgumentException if the project or the name is blank (null, empty or whitespace)
+185 */
+186publicRundeckJob findJob(String project, String groupPath, String name) throws RundeckApiException,
+187 RundeckApiLoginException, IllegalArgumentException {
+188 AssertUtil.notBlank(project, "project is mandatory to find a job !");
+189 AssertUtil.notBlank(name, "job name is mandatory to find a job !");
+190 List<RundeckJob> jobs = getJobs(project, name, groupPath, new String[0]);
+191return jobs.isEmpty() ? null : jobs.get(0);
+192 }
+193
+194/**
+195 * Get the definition of a single job, identified by the given ID
+196 *
+197 * @param jobId identifier of the job - mandatory
+198 * @return a {@link RundeckJob} instance - won't be null
+199 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+200 * @throws RundeckApiLoginException if the login failed
+201 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+202 */
+203publicRundeckJob getJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
+204 IllegalArgumentException {
+205 AssertUtil.notBlank(jobId, "jobId is mandatory to get the details of a job !");
+206returnnewApiCall(this).get("/job/" + jobId, newJobParser("joblist/job"));
+207 }
+208
+209/**
+210 * Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
+211 * end of the job execution)
+212 *
+213 * @param jobId identifier of the job - mandatory
+214 * @return a {@link RundeckExecution} instance for the newly created (and running) execution - won't be null
+215 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+216 * @throws RundeckApiLoginException if the login failed
+217 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+218 * @see #triggerJob(String, Properties, Properties)
+219 * @see #runJob(String)
+220 */
+221publicRundeckExecution triggerJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
+222 IllegalArgumentException {
+223return triggerJob(jobId, null);
+224 }
+225
+226/**
+227 * Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
+228 * end of the job execution)229 * 230 * @param jobId identifier of the job - mandatory
-231 * @return a {@link List} of {@link RundeckExecution} : might be empty, but won't be null
-232 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
-233 * @throws RundeckApiLoginException if the login failed
-234 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
-235 */
-236public List<RundeckExecution> getJobExecutions(String jobId) throws RundeckApiException, RundeckApiLoginException,
-237 IllegalArgumentException {
-238 AssertUtil.notBlank(jobId, "jobId is mandatory to get the executions of a job !");
-239returnnewApiCall(this).get("/job/" + jobId + "/executions",
-240newExecutionsParser("result/executions/execution"));
-241 }
-242
-243/**
-244 * Get a single execution, identified by the given ID
-245 *
-246 * @param executionId identifier of the execution - mandatory
-247 * @return a {@link RundeckExecution} instance - won't be null
-248 * @throws RundeckApiException in case of error when calling the API (non-existent execution with this ID)
-249 * @throws RundeckApiLoginException if the login failed
-250 * @throws IllegalArgumentException if the executionId is null
-251 */
-252publicRundeckExecution getExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException,
-253 IllegalArgumentException {
-254 AssertUtil.notNull(executionId, "executionId is mandatory to get the details of an execution !");
-255returnnewApiCall(this).get("/execution/" + executionId, newExecutionParser("result/executions/execution"));
-256 }
-257
-258public String getUrl() {
-259return url;
-260 }
-261
-262public String getLogin() {
-263return login;
-264 }
-265
-266public String getPassword() {
-267return password;
-268 }
-269
-270 @Override
-271public String toString() {
-272return"RundeckClient [url=" + url + ", login=" + login + ", password=" + password + "]";
-273 }
-274
-275 @Override
-276publicint hashCode() {
-277finalint prime = 31;
-278int result = 1;
-279 result = prime * result + ((login == null) ? 0 : login.hashCode());
-280 result = prime * result + ((password == null) ? 0 : password.hashCode());
-281 result = prime * result + ((url == null) ? 0 : url.hashCode());
-282return result;
-283 }
-284
-285 @Override
-286publicboolean equals(Object obj) {
-287if (this == obj)
-288returntrue;
-289if (obj == null)
-290return false;
-291if (getClass() != obj.getClass())
-292return false;
-293RundeckClient other = (RundeckClient) obj;
-294if (login == null) {
-295if (other.login != null)
-296return false;
-297 } elseif (!login.equals(other.login))
-298return false;
-299if (password == null) {
-300if (other.password != null)
-301return false;
-302 } elseif (!password.equals(other.password))
-303return false;
-304if (url == null) {
-305if (other.url != null)
-306return false;
-307 } elseif (!url.equals(other.url))
-308return false;
-309returntrue;
-310 }
-311
-312 }
+231 * @param options of the job - optional. See {@link OptionsBuilder}.
+232 * @return a {@link RundeckExecution} instance for the newly created (and running) execution - won't be null
+233 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+234 * @throws RundeckApiLoginException if the login failed
+235 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+236 * @see #triggerJob(String, Properties, Properties)
+237 * @see #runJob(String, Properties)
+238 */
+239publicRundeckExecution triggerJob(String jobId, Properties options) throws RundeckApiException,
+240 RundeckApiLoginException, IllegalArgumentException {
+241return triggerJob(jobId, options, null);
+242 }
+243
+244/**
+245 * Trigger the execution of a RunDeck job (identified by the given ID), and return immediately (without waiting the
+246 * end of the job execution)
+247 *
+248 * @param jobId identifier of the job - mandatory
+249 * @param options of the job - optional. See {@link OptionsBuilder}.
+250 * @param nodeFilters for overriding the nodes on which the job will be executed - optional. See
+251 * {@link NodeFiltersBuilder}
+252 * @return a {@link RundeckExecution} instance for the newly created (and running) execution - won't be null
+253 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+254 * @throws RundeckApiLoginException if the login failed
+255 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+256 * @see #triggerJob(String)
+257 * @see #runJob(String, Properties, Properties)
+258 */
+259publicRundeckExecution triggerJob(String jobId, Properties options, Properties nodeFilters)
+260throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+261 AssertUtil.notBlank(jobId, "jobId is mandatory to trigger a job !");
+262 StringBuilder apiPath = new StringBuilder("/job/").append(jobId).append("/run?");
+263 String argString = ParametersUtil.generateArgString(options);
+264if (StringUtils.isNotBlank(argString)) {
+265 apiPath.append("argString=").append(ParametersUtil.urlEncode(argString)).append("&");
+266 }
+267 String filters = ParametersUtil.generateNodeFiltersString(nodeFilters);
+268if (StringUtils.isNotBlank(filters)) {
+269 apiPath.append(filters);
+270 }
+271returnnewApiCall(this).get(apiPath.toString(), new ExecutionParser("result/executions/execution"));
+272 }
+273
+274/**
+275 * Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
+276 * We will poll the RunDeck server at regular interval (every 5 seconds) to know if the execution is finished (or
+277 * aborted) or is still running.
+278 *
+279 * @param jobId identifier of the job - mandatory
+280 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+281 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+282 * @throws RundeckApiLoginException if the login failed
+283 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+284 * @see #triggerJob(String)
+285 * @see #runJob(String, Properties, Properties, long, TimeUnit)
+286 */
+287publicRundeckExecution runJob(String jobId) throws RundeckApiException, RundeckApiLoginException,
+288 IllegalArgumentException {
+289return runJob(jobId, null);
+290 }
+291
+292/**
+293 * Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
+294 * We will poll the RunDeck server at regular interval (every 5 seconds) to know if the execution is finished (or
+295 * aborted) or is still running.
+296 *
+297 * @param jobId identifier of the job - mandatory
+298 * @param options of the job - optional. See {@link OptionsBuilder}.
+299 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+300 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+301 * @throws RundeckApiLoginException if the login failed
+302 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+303 * @see #triggerJob(String, Properties)
+304 * @see #runJob(String, Properties, Properties, long, TimeUnit)
+305 */
+306publicRundeckExecution runJob(String jobId, Properties options) throws RundeckApiException,
+307 RundeckApiLoginException, IllegalArgumentException {
+308return runJob(jobId, options, null);
+309 }
+310
+311/**
+312 * Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
+313 * We will poll the RunDeck server at regular interval (every 5 seconds) to know if the execution is finished (or
+314 * aborted) or is still running.
+315 *
+316 * @param jobId identifier of the job - mandatory
+317 * @param options of the job - optional. See {@link OptionsBuilder}.
+318 * @param nodeFilters for overriding the nodes on which the job will be executed - optional. See
+319 * {@link NodeFiltersBuilder}
+320 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+321 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+322 * @throws RundeckApiLoginException if the login failed
+323 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+324 * @see #triggerJob(String, Properties, Properties)
+325 * @see #runJob(String, Properties, Properties, long, TimeUnit)
+326 */
+327publicRundeckExecution runJob(String jobId, Properties options, Properties nodeFilters)
+328throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+329return runJob(jobId, options, nodeFilters, 5, TimeUnit.SECONDS);
+330 }
+331
+332/**
+333 * Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
+334 * We will poll the RunDeck server at regular interval (configured by the poolingInterval/poolingUnit couple) to
+335 * know if the execution is finished (or aborted) or is still running.
+336 *
+337 * @param jobId identifier of the job - mandatory
+338 * @param options of the job - optional. See {@link OptionsBuilder}.
+339 * @param poolingInterval for checking the status of the execution. Must be > 0.
+340 * @param poolingUnit unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
+341 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+342 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+343 * @throws RundeckApiLoginException if the login failed
+344 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+345 * @see #triggerJob(String, Properties)
+346 * @see #runJob(String, Properties, Properties, long, TimeUnit)
+347 */
+348publicRundeckExecution runJob(String jobId, Properties options, long poolingInterval, TimeUnit poolingUnit)
+349throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+350return runJob(jobId, options, null, poolingInterval, poolingUnit);
+351 }
+352
+353/**
+354 * Run a RunDeck job (identified by the given ID), and wait until its execution is finished (or aborted) to return.
+355 * We will poll the RunDeck server at regular interval (configured by the poolingInterval/poolingUnit couple) to
+356 * know if the execution is finished (or aborted) or is still running.
+357 *
+358 * @param jobId identifier of the job - mandatory
+359 * @param options of the job - optional. See {@link OptionsBuilder}.
+360 * @param nodeFilters for overriding the nodes on which the job will be executed - optional. See
+361 * {@link NodeFiltersBuilder}
+362 * @param poolingInterval for checking the status of the execution. Must be > 0.
+363 * @param poolingUnit unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
+364 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+365 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+366 * @throws RundeckApiLoginException if the login failed
+367 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+368 * @see #triggerJob(String, Properties)
+369 * @see #runJob(String, Properties, Properties, long, TimeUnit)
+370 */
+371publicRundeckExecution runJob(String jobId, Properties options, Properties nodeFilters, long poolingInterval,
+372 TimeUnit poolingUnit) throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+373if (poolingInterval <= 0) {
+374 poolingInterval = 5;
+375 poolingUnit = TimeUnit.SECONDS;
+376 }
+377if (poolingUnit == null) {
+378 poolingUnit = TimeUnit.SECONDS;
+379 }
+380
+381RundeckExecution execution = triggerJob(jobId, options, nodeFilters);
+382while (ExecutionStatus.RUNNING.equals(execution.getStatus())) {
+383try {
+384 Thread.sleep(poolingUnit.toMillis(poolingInterval));
+385 } catch (InterruptedException e) {
+386break;
+387 }
+388 execution = getExecution(execution.getId());
+389 }
+390return execution;
+391 }
+392
+393/*
+394 * Ad-hoc commands
+395 */
+396
+397/**
+398 * Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
+399 * The command will not be dispatched to nodes, but be executed on the RunDeck server.
+400 *
+401 * @param project name of the project - mandatory
+402 * @param command to be executed - mandatory
+403 * @return a {@link RundeckExecution} instance for the newly created (and running) execution - won't be null
+404 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+405 * @throws RundeckApiLoginException if the login failed
+406 * @throws IllegalArgumentException if the project or command is blank (null, empty or whitespace)
+407 * @see #triggerAdhocCommand(String, String, Properties)
+408 * @see #runAdhocCommand(String, String)
+409 */
+410publicRundeckExecution triggerAdhocCommand(String project, String command) throws RundeckApiException,
+411 RundeckApiLoginException, IllegalArgumentException {
+412return triggerAdhocCommand(project, command, null);
+413 }
+414
+415/**
+416 * Trigger the execution of an ad-hoc command, and return immediately (without waiting the end of the execution).
+417 * The command will be dispatched to nodes, accordingly to the nodeFilters parameter.
+418 *
+419 * @param project name of the project - mandatory
+420 * @param command to be executed - mandatory
+421 * @param nodeFilters for selecting nodes on which the command will be executed. See {@link NodeFiltersBuilder}
+422 * @return a {@link RundeckExecution} instance for the newly created (and running) execution - won't be null
+423 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+424 * @throws RundeckApiLoginException if the login failed
+425 * @throws IllegalArgumentException if the project or command is blank (null, empty or whitespace)
+426 * @see #triggerAdhocCommand(String, String)
+427 * @see #runAdhocCommand(String, String, Properties)
+428 */
+429publicRundeckExecution triggerAdhocCommand(String project, String command, Properties nodeFilters)
+430throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+431 AssertUtil.notBlank(project, "project is mandatory to trigger an ad-hoc command !");
+432 AssertUtil.notBlank(command, "command is mandatory to trigger an ad-hoc command !");
+433 StringBuilder apiPath = new StringBuilder("/run/command");
+434 apiPath.append("?project=").append(project);
+435 apiPath.append("&exec=").append(ParametersUtil.urlEncode(command));
+436 String filters = ParametersUtil.generateNodeFiltersString(nodeFilters);
+437if (StringUtils.isNotBlank(filters)) {
+438 apiPath.append("&").append(filters);
+439 }
+440RundeckExecution execution = newApiCall(this).get(apiPath.toString(), new ExecutionParser("result/execution"));
+441// the first call just returns the ID of the execution, so we need another call to get a "real" execution
+442return getExecution(execution.getId());
+443 }
+444
+445/**
+446 * Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
+447 * server at regular interval (every 5 seconds) to know if the execution is finished (or aborted) or is still
+448 * running. The command will not be dispatched to nodes, but be executed on the RunDeck server.
+449 *
+450 * @param project name of the project - mandatory
+451 * @param command to be executed - mandatory
+452 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+453 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+454 * @throws RundeckApiLoginException if the login failed
+455 * @throws IllegalArgumentException if the project or command is blank (null, empty or whitespace)
+456 * @see #runAdhocCommand(String, String, Properties, long, TimeUnit)
+457 * @see #triggerAdhocCommand(String, String)
+458 */
+459publicRundeckExecution runAdhocCommand(String project, String command) throws RundeckApiException,
+460 RundeckApiLoginException, IllegalArgumentException {
+461return runAdhocCommand(project, command, null);
+462 }
+463
+464/**
+465 * Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
+466 * server at regular interval (configured by the poolingInterval/poolingUnit couple) to know if the execution is
+467 * finished (or aborted) or is still running. The command will not be dispatched to nodes, but be executed on the
+468 * RunDeck server.
+469 *
+470 * @param project name of the project - mandatory
+471 * @param command to be executed - mandatory
+472 * @param poolingInterval for checking the status of the execution. Must be > 0.
+473 * @param poolingUnit unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
+474 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+475 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+476 * @throws RundeckApiLoginException if the login failed
+477 * @throws IllegalArgumentException if the project or command is blank (null, empty or whitespace)
+478 * @see #runAdhocCommand(String, String, Properties, long, TimeUnit)
+479 * @see #triggerAdhocCommand(String, String)
+480 */
+481publicRundeckExecution runAdhocCommand(String project, String command, long poolingInterval, TimeUnit poolingUnit)
+482throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+483return runAdhocCommand(project, command, null, poolingInterval, poolingUnit);
+484 }
+485
+486/**
+487 * Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
+488 * server at regular interval (every 5 seconds) to know if the execution is finished (or aborted) or is still
+489 * running. The command will be dispatched to nodes, accordingly to the nodeFilters parameter.
+490 *
+491 * @param project name of the project - mandatory
+492 * @param command to be executed - mandatory
+493 * @param nodeFilters for selecting nodes on which the command will be executed. See {@link NodeFiltersBuilder}
+494 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+495 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+496 * @throws RundeckApiLoginException if the login failed
+497 * @throws IllegalArgumentException if the project or command is blank (null, empty or whitespace)
+498 * @see #runAdhocCommand(String, String, Properties, long, TimeUnit)
+499 * @see #triggerAdhocCommand(String, String, Properties)
+500 */
+501publicRundeckExecution runAdhocCommand(String project, String command, Properties nodeFilters)
+502throws RundeckApiException, RundeckApiLoginException, IllegalArgumentException {
+503return runAdhocCommand(project, command, nodeFilters, 5, TimeUnit.SECONDS);
+504 }
+505
+506/**
+507 * Run an ad-hoc command, and wait until its execution is finished (or aborted) to return. We will poll the RunDeck
+508 * server at regular interval (configured by the poolingInterval/poolingUnit couple) to know if the execution is
+509 * finished (or aborted) or is still running. The command will be dispatched to nodes, accordingly to the
+510 * nodeFilters parameter.
+511 *
+512 * @param project name of the project - mandatory
+513 * @param command to be executed - mandatory
+514 * @param nodeFilters for selecting nodes on which the command will be executed. See {@link NodeFiltersBuilder}
+515 * @param poolingInterval for checking the status of the execution. Must be > 0.
+516 * @param poolingUnit unit (seconds, milli-seconds, ...) of the interval. Default to seconds.
+517 * @return a {@link RundeckExecution} instance for the (finished/aborted) execution - won't be null
+518 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+519 * @throws RundeckApiLoginException if the login failed
+520 * @throws IllegalArgumentException if the project or command is blank (null, empty or whitespace)
+521 * @see #triggerAdhocCommand(String, String, Properties)
+522 */
+523publicRundeckExecution runAdhocCommand(String project, String command, Properties nodeFilters,
+524long poolingInterval, TimeUnit poolingUnit) throws RundeckApiException, RundeckApiLoginException,
+525 IllegalArgumentException {
+526if (poolingInterval <= 0) {
+527 poolingInterval = 5;
+528 poolingUnit = TimeUnit.SECONDS;
+529 }
+530if (poolingUnit == null) {
+531 poolingUnit = TimeUnit.SECONDS;
+532 }
+533
+534RundeckExecution execution = triggerAdhocCommand(project, command, nodeFilters);
+535while (ExecutionStatus.RUNNING.equals(execution.getStatus())) {
+536try {
+537 Thread.sleep(poolingUnit.toMillis(poolingInterval));
+538 } catch (InterruptedException e) {
+539break;
+540 }
+541 execution = getExecution(execution.getId());
+542 }
+543return execution;
+544 }
+545
+546/*
+547 * Executions
+548 */
+549
+550/**
+551 * Get the running executions for the given project
+552 *
+553 * @param project name of the project - mandatory
+554 * @return a {@link List} of {@link RundeckExecution} : might be empty, but won't be null
+555 * @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
+556 * @throws RundeckApiLoginException if the login failed
+557 * @throws IllegalArgumentException if the project is blank (null, empty or whitespace)
+558 */
+559public List<RundeckExecution> getRunningExecutions(String project) throws RundeckApiException,
+560 RundeckApiLoginException, IllegalArgumentException {
+561 AssertUtil.notBlank(project, "project is mandatory to trigger an ad-hoc command !");
+562returnnewApiCall(this).get("/executions/running?project=" + project,
+563newExecutionsParser("result/executions/execution"));
+564 }
+565
+566/**
+567 * Get the executions of the given job
+568 *
+569 * @param jobId identifier of the job - mandatory
+570 * @return a {@link List} of {@link RundeckExecution} : might be empty, but won't be null
+571 * @throws RundeckApiException in case of error when calling the API (non-existent job with this ID)
+572 * @throws RundeckApiLoginException if the login failed
+573 * @throws IllegalArgumentException if the jobId is blank (null, empty or whitespace)
+574 */
+575public List<RundeckExecution> getJobExecutions(String jobId) throws RundeckApiException, RundeckApiLoginException,
+576 IllegalArgumentException {
+577 AssertUtil.notBlank(jobId, "jobId is mandatory to get the executions of a job !");
+578returnnewApiCall(this).get("/job/" + jobId + "/executions",
+579newExecutionsParser("result/executions/execution"));
+580 }
+581
+582/**
+583 * Get a single execution, identified by the given ID
+584 *
+585 * @param executionId identifier of the execution - mandatory
+586 * @return a {@link RundeckExecution} instance - won't be null
+587 * @throws RundeckApiException in case of error when calling the API (non-existent execution with this ID)
+588 * @throws RundeckApiLoginException if the login failed
+589 * @throws IllegalArgumentException if the executionId is null
+590 */
+591publicRundeckExecution getExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException,
+592 IllegalArgumentException {
+593 AssertUtil.notNull(executionId, "executionId is mandatory to get the details of an execution !");
+594returnnewApiCall(this).get("/execution/" + executionId, newExecutionParser("result/executions/execution"));
+595 }
+596
+597public String getUrl() {
+598return url;
+599 }
+600
+601public String getLogin() {
+602return login;
+603 }
+604
+605public String getPassword() {
+606return password;
+607 }
+608
+609 @Override
+610public String toString() {
+611return"RundeckClient [url=" + url + ", login=" + login + ", password=" + password + "]";
+612 }
+613
+614 @Override
+615publicint hashCode() {
+616finalint prime = 31;
+617int result = 1;
+618 result = prime * result + ((login == null) ? 0 : login.hashCode());
+619 result = prime * result + ((password == null) ? 0 : password.hashCode());
+620 result = prime * result + ((url == null) ? 0 : url.hashCode());
+621return result;
+622 }
+623
+624 @Override
+625publicboolean equals(Object obj) {
+626if (this == obj)
+627returntrue;
+628if (obj == null)
+629return false;
+630if (getClass() != obj.getClass())
+631return false;
+632RundeckClient other = (RundeckClient) obj;
+633if (login == null) {
+634if (other.login != null)
+635return false;
+636 } elseif (!login.equals(other.login))
+637return false;
+638if (password == null) {
+639if (other.password != null)
+640return false;
+641 } elseif (!password.equals(other.password))
+642return false;
+643if (url == null) {
+644if (other.url != null)
+645return false;
+646 } elseif (!url.equals(other.url))
+647return false;
+648returntrue;
+649 }
+650
+651 }
diff --git a/xref/org/rundeck/api/domain/RundeckExecution.html b/xref/org/rundeck/api/domain/RundeckExecution.html
index bdded8b..10c948d 100644
--- a/xref/org/rundeck/api/domain/RundeckExecution.html
+++ b/xref/org/rundeck/api/domain/RundeckExecution.html
@@ -12,198 +12,228 @@
23import java.io.Serializable;
4import java.util.Date;
-5
-6/**
-7 * Represents a RunDeck execution, usually triggered by an API call. An execution could be a {@link RundeckJob}
-8 * execution or an "ad-hoc" execution.
-9 *
-10 * @author Vincent Behar
-11 */
-12publicclassRundeckExecutionimplements Serializable {
-13
-14privatestaticfinallong serialVersionUID = 1L;
-15
-16private Long id;
-17
-18private String url;
-19
-20privateExecutionStatus status;
-21
-22/** Optional - only if it is a job execution */
-23privateRundeckJob job;
-24
-25private String startedBy;
-26
-27private Date startedAt;
-28
-29/** only if the execution has ended */
-30private Date endedAt;
-31
-32/** only if the execution was aborted */
-33private String abortedBy;
-34
-35private String description;
-36
-37public Long getId() {
-38return id;
-39 }
-40
-41publicvoid setId(Long id) {
-42this.id = id;
-43 }
-44
-45public String getUrl() {
-46return url;
+5import java.util.concurrent.TimeUnit;
+6
+7/**
+8 * Represents a RunDeck execution, usually triggered by an API call. An execution could be a {@link RundeckJob}
+9 * execution or an "ad-hoc" execution.
+10 *
+11 * @author Vincent Behar
+12 */
+13publicclassRundeckExecutionimplements Serializable {
+14
+15privatestaticfinallong serialVersionUID = 1L;
+16
+17private Long id;
+18
+19private String url;
+20
+21privateExecutionStatus status;
+22
+23/** Optional - only if it is a job execution */
+24privateRundeckJob job;
+25
+26private String startedBy;
+27
+28private Date startedAt;
+29
+30/** only if the execution has ended */
+31private Date endedAt;
+32
+33/** only if the execution was aborted */
+34private String abortedBy;
+35
+36private String description;
+37
+38/**
+39 * @return the duration of the execution in milliseconds (or null if the duration is still running, or has been
+40 * aborted)
+41 */
+42public Long getDurationInMillis() {
+43if (startedAt == null || endedAt == null) {
+44returnnull;
+45 }
+46return endedAt.getTime() - startedAt.getTime();
47 }
48
-49publicvoid setUrl(String url) {
-50this.url = url;
-51 }
-52
-53publicExecutionStatus getStatus() {
-54return status;
-55 }
-56
-57publicvoid setStatus(ExecutionStatus status) {
-58this.status = status;
-59 }
-60
-61publicRundeckJob getJob() {
-62return job;
-63 }
-64
-65publicvoid setJob(RundeckJob job) {
-66this.job = job;
-67 }
-68
-69public String getStartedBy() {
-70return startedBy;
-71 }
-72
-73publicvoid setStartedBy(String startedBy) {
-74this.startedBy = startedBy;
-75 }
-76
-77public Date getStartedAt() {
-78return (startedAt != null) ? new Date(startedAt.getTime()) : null;
-79 }
-80
-81publicvoid setStartedAt(Date startedAt) {
-82this.startedAt = ((startedAt != null) ? new Date(startedAt.getTime()) : null);
-83 }
-84
-85public Date getEndedAt() {
-86return (endedAt != null) ? new Date(endedAt.getTime()) : null;
-87 }
-88
-89publicvoid setEndedAt(Date endedAt) {
-90this.endedAt = ((endedAt != null) ? new Date(endedAt.getTime()) : null);
-91 }
-92
-93public String getAbortedBy() {
-94return abortedBy;
-95 }
-96
-97publicvoid setAbortedBy(String abortedBy) {
-98this.abortedBy = abortedBy;
-99 }
-100
-101public String getDescription() {
-102return description;
-103 }
-104
-105publicvoid setDescription(String description) {
-106this.description = description;
-107 }
-108
-109 @Override
-110public String toString() {
-111return"RundeckExecution [abortedBy=" + abortedBy + ", description=" + description + ", endedAt=" + endedAt
-112 + ", id=" + id + ", job=" + job + ", startedAt=" + startedAt + ", startedBy=" + startedBy + ", status="
-113 + status + ", url=" + url + "]";
-114 }
-115
-116 @Override
-117publicint hashCode() {
-118finalint prime = 31;
-119int result = 1;
-120 result = prime * result + ((abortedBy == null) ? 0 : abortedBy.hashCode());
-121 result = prime * result + ((description == null) ? 0 : description.hashCode());
-122 result = prime * result + ((endedAt == null) ? 0 : endedAt.hashCode());
-123 result = prime * result + ((id == null) ? 0 : id.hashCode());
-124 result = prime * result + ((job == null) ? 0 : job.hashCode());
-125 result = prime * result + ((startedAt == null) ? 0 : startedAt.hashCode());
-126 result = prime * result + ((startedBy == null) ? 0 : startedBy.hashCode());
-127 result = prime * result + ((status == null) ? 0 : status.hashCode());
-128 result = prime * result + ((url == null) ? 0 : url.hashCode());
-129return result;
-130 }
-131
-132 @Override
-133publicboolean equals(Object obj) {
-134if (this == obj)
-135returntrue;
-136if (obj == null)
-137return false;
-138if (getClass() != obj.getClass())
-139return false;
-140RundeckExecution other = (RundeckExecution) obj;
-141if (abortedBy == null) {
-142if (other.abortedBy != null)
-143return false;
-144 } elseif (!abortedBy.equals(other.abortedBy))
-145return false;
-146if (description == null) {
-147if (other.description != null)
-148return false;
-149 } elseif (!description.equals(other.description))
-150return false;
-151if (endedAt == null) {
-152if (other.endedAt != null)
-153return false;
-154 } elseif (!endedAt.equals(other.endedAt))
-155return false;
-156if (id == null) {
-157if (other.id != null)
-158return false;
-159 } elseif (!id.equals(other.id))
-160return false;
-161if (job == null) {
-162if (other.job != null)
-163return false;
-164 } elseif (!job.equals(other.job))
-165return false;
-166if (startedAt == null) {
-167if (other.startedAt != null)
-168return false;
-169 } elseif (!startedAt.equals(other.startedAt))
-170return false;
-171if (startedBy == null) {
-172if (other.startedBy != null)
+49/**
+50 * @return the duration of the execution in seconds (or null if the duration is still running, or has been aborted)
+51 */
+52public Long getDurationInSeconds() {
+53 Long durationInMillis = getDurationInMillis();
+54if (durationInMillis == null) {
+55returnnull;
+56 }
+57return TimeUnit.MILLISECONDS.toSeconds(durationInMillis);
+58 }
+59
+60public Long getId() {
+61return id;
+62 }
+63
+64publicvoid setId(Long id) {
+65this.id = id;
+66 }
+67
+68public String getUrl() {
+69return url;
+70 }
+71
+72publicvoid setUrl(String url) {
+73this.url = url;
+74 }
+75
+76/**
+77 * @return the status of the execution - see {@link ExecutionStatus}
+78 */
+79publicExecutionStatus getStatus() {
+80return status;
+81 }
+82
+83publicvoid setStatus(ExecutionStatus status) {
+84this.status = status;
+85 }
+86
+87/**
+88 * @return the {@link RundeckJob} associated with this execution, or null in the case of an ad-hoc execution
+89 * (command or script)
+90 */
+91publicRundeckJob getJob() {
+92return job;
+93 }
+94
+95publicvoid setJob(RundeckJob job) {
+96this.job = job;
+97 }
+98
+99public String getStartedBy() {
+100return startedBy;
+101 }
+102
+103publicvoid setStartedBy(String startedBy) {
+104this.startedBy = startedBy;
+105 }
+106
+107public Date getStartedAt() {
+108return (startedAt != null) ? new Date(startedAt.getTime()) : null;
+109 }
+110
+111publicvoid setStartedAt(Date startedAt) {
+112this.startedAt = ((startedAt != null) ? new Date(startedAt.getTime()) : null);
+113 }
+114
+115public Date getEndedAt() {
+116return (endedAt != null) ? new Date(endedAt.getTime()) : null;
+117 }
+118
+119publicvoid setEndedAt(Date endedAt) {
+120this.endedAt = ((endedAt != null) ? new Date(endedAt.getTime()) : null);
+121 }
+122
+123public String getAbortedBy() {
+124return abortedBy;
+125 }
+126
+127publicvoid setAbortedBy(String abortedBy) {
+128this.abortedBy = abortedBy;
+129 }
+130
+131public String getDescription() {
+132return description;
+133 }
+134
+135publicvoid setDescription(String description) {
+136this.description = description;
+137 }
+138
+139 @Override
+140public String toString() {
+141return"RundeckExecution [id=" + id + ", description=" + description + ", url=" + url + ", status=" + status
+142 + ", startedBy=" + startedBy + ", startedAt=" + startedAt + ", endedAt=" + endedAt
+143 + ", durationInSeconds=" + getDurationInSeconds() + ", abortedBy=" + abortedBy + ", job=" + job + "]";
+144 }
+145
+146 @Override
+147publicint hashCode() {
+148finalint prime = 31;
+149int result = 1;
+150 result = prime * result + ((abortedBy == null) ? 0 : abortedBy.hashCode());
+151 result = prime * result + ((description == null) ? 0 : description.hashCode());
+152 result = prime * result + ((endedAt == null) ? 0 : endedAt.hashCode());
+153 result = prime * result + ((id == null) ? 0 : id.hashCode());
+154 result = prime * result + ((job == null) ? 0 : job.hashCode());
+155 result = prime * result + ((startedAt == null) ? 0 : startedAt.hashCode());
+156 result = prime * result + ((startedBy == null) ? 0 : startedBy.hashCode());
+157 result = prime * result + ((status == null) ? 0 : status.hashCode());
+158 result = prime * result + ((url == null) ? 0 : url.hashCode());
+159return result;
+160 }
+161
+162 @Override
+163publicboolean equals(Object obj) {
+164if (this == obj)
+165returntrue;
+166if (obj == null)
+167return false;
+168if (getClass() != obj.getClass())
+169return false;
+170RundeckExecution other = (RundeckExecution) obj;
+171if (abortedBy == null) {
+172if (other.abortedBy != null)
173return false;
-174 } elseif (!startedBy.equals(other.startedBy))
+174 } elseif (!abortedBy.equals(other.abortedBy))
175return false;
-176if (status == null) {
-177if (other.status != null)
+176if (description == null) {
+177if (other.description != null)
178return false;
-179 } elseif (!status.equals(other.status))
+179 } elseif (!description.equals(other.description))
180return false;
-181if (url == null) {
-182if (other.url != null)
+181if (endedAt == null) {
+182if (other.endedAt != null)
183return false;
-184 } elseif (!url.equals(other.url))
+184 } elseif (!endedAt.equals(other.endedAt))
185return false;
-186returntrue;
-187 }
-188
-189/**
-190 * The status of an execution
-191 */
-192publicstatic enum ExecutionStatus {
-193 RUNNING, SUCCEEDED, FAILED, ABORTED;
-194 }
-195
-196 }
+186if (id == null) {
+187if (other.id != null)
+188return false;
+189 } elseif (!id.equals(other.id))
+190return false;
+191if (job == null) {
+192if (other.job != null)
+193return false;
+194 } elseif (!job.equals(other.job))
+195return false;
+196if (startedAt == null) {
+197if (other.startedAt != null)
+198return false;
+199 } elseif (!startedAt.equals(other.startedAt))
+200return false;
+201if (startedBy == null) {
+202if (other.startedBy != null)
+203return false;
+204 } elseif (!startedBy.equals(other.startedBy))
+205return false;
+206if (status == null) {
+207if (other.status != null)
+208return false;
+209 } elseif (!status.equals(other.status))
+210return false;
+211if (url == null) {
+212if (other.url != null)
+213return false;
+214 } elseif (!url.equals(other.url))
+215return false;
+216returntrue;
+217 }
+218
+219/**
+220 * The status of an execution
+221 */
+222publicstatic enum ExecutionStatus {
+223 RUNNING, SUCCEEDED, FAILED, ABORTED;
+224 }
+225
+226 }
diff --git a/xref/org/rundeck/api/parser/ExecutionParser.html b/xref/org/rundeck/api/parser/ExecutionParser.html
index 6567ee6..e2cb193 100644
--- a/xref/org/rundeck/api/parser/ExecutionParser.html
+++ b/xref/org/rundeck/api/parser/ExecutionParser.html
@@ -46,26 +46,32 @@
3637 execution.setId(Long.valueOf(execNode.valueOf("@id")));
38 execution.setUrl(StringUtils.trimToNull(execNode.valueOf("@href")));
-39 execution.setStatus(ExecutionStatus.valueOf(StringUtils.upperCase(execNode.valueOf("@status"))));
-40 execution.setDescription(StringUtils.trimToNull(execNode.valueOf("description")));
-41 execution.setStartedBy(StringUtils.trimToNull(execNode.valueOf("user")));
-42 execution.setStartedAt(new Date(Long.valueOf(execNode.valueOf("date-started/@unixtime"))));
-43 execution.setAbortedBy(StringUtils.trimToNull(execNode.valueOf("abortedby")));
-44 String endedAt = StringUtils.trimToNull(execNode.valueOf("date-ended/@unixtime"));
-45if (endedAt != null) {
-46 execution.setEndedAt(new Date(Long.valueOf(endedAt)));
-47 }
-48
-49 Node jobNode = execNode.selectSingleNode("job");
-50if (jobNode != null) {
-51RundeckJob job = newJobParser().parseNode(jobNode);
-52 execution.setJob(job);
+39try {
+40 execution.setStatus(ExecutionStatus.valueOf(StringUtils.upperCase(execNode.valueOf("@status"))));
+41 } catch (IllegalArgumentException e) {
+42 }
+43 execution.setDescription(StringUtils.trimToNull(execNode.valueOf("description")));
+44 execution.setStartedBy(StringUtils.trimToNull(execNode.valueOf("user")));
+45 execution.setAbortedBy(StringUtils.trimToNull(execNode.valueOf("abortedby")));
+46 String startedAt = StringUtils.trimToNull(execNode.valueOf("date-started/@unixtime"));
+47if (startedAt != null) {
+48 execution.setStartedAt(new Date(Long.valueOf(startedAt)));
+49 }
+50 String endedAt = StringUtils.trimToNull(execNode.valueOf("date-ended/@unixtime"));
+51if (endedAt != null) {
+52 execution.setEndedAt(new Date(Long.valueOf(endedAt)));
53 }
54
-55return execution;
-56 }
-57
-58 }
+55 Node jobNode = execNode.selectSingleNode("job");
+56if (jobNode != null) {
+57RundeckJob job = newJobParser().parseNode(jobNode);
+58 execution.setJob(job);
+59 }
+60
+61return execution;
+62 }
+63
+64 }
diff --git a/xref/org/rundeck/api/util/NodeFiltersBuilder.html b/xref/org/rundeck/api/util/NodeFiltersBuilder.html
new file mode 100644
index 0000000..8b310ba
--- /dev/null
+++ b/xref/org/rundeck/api/util/NodeFiltersBuilder.html
@@ -0,0 +1,288 @@
+
+
+
+
+NodeFiltersBuilder xref
+
+
+
+