Jump to: navigation, search

Hudson-ci/help/remote access api

Hudson Continuous Integration Server
Website
Download
Community
Mailing ListForumsIRCmattermost
Bugzilla
OpenHelp WantedBug Day
Contribute
Browse Source
Hudson-bust.png Help - Remote Access API











Help Index

Summary

Hudson provides machine-consumable remote access API to its functionalities. It comes in two built-in flavors, with an additional alternative REST module as a separate plugin:

  1. XML
  2. JSON with JSONP support

Remote access API is offered in a REST-like style. That is, there is no single entry point for all features, and instead they are available under the ".../api/" URL where "..." portion is the data that it acts on.

For example, if your Hudson installation sits at http://deadlock.netbeans.org/hudson/, http://deadlock.netbeans.org/hudson/api/ will give you HTML lists of all available functionalities that act on the Hudson root. For example, from here you can access all the jobs on Hudson via XML/JSON. Or if you want to access information about a particular build at http://deadlock.netbeans.org/hudson/job/trunk/lastSuccessfulBuild/, then go to http://deadlock.netbeans.org/hudson/job/trunk/lastSuccessfulBuild/api/ and you'll see the list of functionalities for the build.

What can you do with it?

Remote API can be used to do things like these:

  1. Retrieve information from Hudson for programmatic consumption.
  2. Trigger a new build
  3. Create/copy jobs

Submitting jobs

For a job with no parameters, you need merely go an HTTP GET on:

HUDSON_URL/job/JOBNAME/build?token=TOKEN

where TOKEN is set up in the job configuration.

If you have parameters, you need to send JSON. Here's a snipped of shell, with a few extra newlines to be more readable.

json="{\"parameter\": [{\"name\": \"taskfile\", \"value\": \"$taskfile\"}, 
      {\"name\": \"task\", \"value\": \"$task\"}, {\"name\": \"jobParameters\", \"value\": \"$jobargs\"}], 
      \"\": \"\"}" 
      url=http://hudson.basistech.net/job/benson-segmentation-training/build curl -X POST $url -d token=zorn --data-urlencode json="$json"

Creating and Copying Jobs

You can copy a job in the same Hudson or create a job from config.xml in any Hudson using the createItem command, as documented in:

http://HUDSON_HOST/api/

Where HUDSON_HOST is replaced by your host name.

You can obtain the config.xml file for a job by:

http://HUDSON_HOST/job/JOBNAME/config.xml

E.g., to save it to a file:

curl -u USERNAME http://HUDSON_HOST/job/JOBNAME/config.xml > config.xml

The USERNAME is required when security is enabled; curl will prompt for password before fetching config.xml.

When the team feature is enabled, you can use the create-job and copy-job CLI commands to create a job within a team.

Remote API and Security

When your Hudson is secured, you can use HTTP BASIC authentication to authenticate remote API requests. See Authenticating scripted clients for more details.

Sample code

A simple client written by Kohsuke Kawaguchi is available to demonstrate how you can invoke the XML from Java. The code is reproduced below for convenience:

Unsecured Server Version

public class Main {
    public static void main(String[] args) throws Exception {
        // every Hudson model object exposes the .../api/xml, but in this example
        // we'll just take the root object as an example
        URL url = new URL("http://deadlock.netbeans.org/hudson/api/xml");
        // if you are calling security-enabled Hudson and
        // need to invoke operations and APIs that are protected,
        // consult the 'SecuredMain" class
        // in this package for an example using HttpClient.
        // read it into DOM.
        Document dom = new SAXReader().read(url);
       // scan through the job list and print its status
        for( Element job : (List<Element>)dom.getRootElement().elements("job")) {
            System.out.println(String.format("Name:%s\tStatus:%s",
                job.elementText("name"), job.elementText("color")));
        }
    }
}
 

Secured Server Version

public class SecuredMain {
/**
 * On most security configurations, except "delegate to servlet container"
 * authentication, simply sending in the BASIC authentication pre-emptively works.
 * See http://hc.apache.org/httpclient-3.x/authentication.html
 * for how to configure pre-emptive authentication.
 *
 * However, in the "delegate to servlet container" mode, BASIC auth
 * support depends on the container implementation, and hence inherently
 * unreliable. The following code uses Jakarta Commons HTTP client
 * to work around this problem by essentially emulating what the user
 * does through the browser.
 *
 * The code first emulates a click of the "login" link, then submit
 * the login form. Once that's done, you are authenticated, so you
 * can access the information you wanted. This is all possible
 * because {@link HttpClient} maintains a cookie jar in it.
 */
 public static void main(String[] args) throws IOException {
   HttpClient client = new HttpClient();
   String hostName = "http://localhost:8080/";
   GetMethod loginLink = new GetMethod(hostName+"loginEntry");
   client.executeMethod(loginLink);<br> checkResult(loginLink.getStatusCode());
   String location = hostName+"j_security_check";
   while(true) {
     PostMethod loginMethod = new PostMethod(location);
     // TODO: replace with real user name and password
     loginMethod.addParameter("j_username", "username"); 
     loginMethod.addParameter("j_password", "password");
     loginMethod.addParameter("action", "login");
     client.executeMethod(loginMethod);
     if(loginMethod.getStatusCode()/100==3) {
       // Commons HTTP client refuses to handle redirects for POST
       // so we have to do it manually.
       location = loginMethod.getResponseHeader("Location").getValue();
       continue;
     }
     checkResult(loginMethod.getStatusCode());
     break;
   }

   HttpMethod method = new GetMethod(hostName+"log");
   client.executeMethod(method);
   checkResult(method.getStatusCode());

   System.out.println(method.getResponseBodyAsString());
 }

 private static void checkResult(int i) throws IOException {
   if(i/100!=2)
   throw new IOException();
 }

Using XPath

XPath Selection

The XML API supports a selection by XPath by using the query parameter 'xpath'. This is convenient for extracting information in environments where XML manipulation is tedious (such as shell script.)

Heres a simple example where we need to parse out the duration of the last successful build with a single URL.

https://hudson.eclipse.org/hudson/job/hudson-core/lastSuccessfulBuild/api/xml?xpath=/*/duration/text()

XPath Exclusion

Similar to the 'xpath' query parameter above, you can use (possibly multiple) 'exclude' query patterns to exclude nodes from the resulting XML. All the nodes that match the specified XPath will be removed from the XML.

Controlling the Amount of Data you Fetch

Sometimes the remote API doesn't give you enough information in one call. For example, if you'd like to find out all the last successful build of a given view, you'd realize that the invocation to the remote API of the view won't give you this, and you'd have to recursively call the remote API of each project to find this out. The depth control, solves this problem. To understand this feature, it's good to start with how the remote API works.

The data model that Hudson maintains internally can be thought of as a big tree structure, and when you make a remote API call, you are getting a small subtree of it. The subtree is rooted at the object for which you made a remote API call, and the sub-tree is cut beyond certain depth to avoid returning too much data. You can adjust this cut-off behavior by specifying the depth query parameter. When you specify a positive depth value, the subtree cut-off happens that much later.

So the net result is, if you specify a bigger depth value, you'll see that the remote API will now return more data. Because of the algorithm, this works in such a way that the data returned by a bigger depth value includes all the data returned by smaller depth value.

depth Query Parameter

In all formats, the depth query parameter can be used to control the amount of data you'll receive. The default is depth=0, but by increasing this value you can get a lot of data by single remote API invocation (the downside is bigger bandwidth requirement.) You can try this yourself to see the effect:

http://127.0.0.1:8080/api/xml?depth=0

v's

http://127.0.0.1:8080/api/xml?depth=2

Note: The data created by a smaller depth value is always a subset of the data created by a bigger depth value.

tree Query Parameter

A newer alternative to depth is the tree query parameter. This works with any format, e.g. JSON; is more efficient than using depth with exclude xpath expressions (since information does not need to be generated on the server and then discarded); and may be easier to use, since you need only know what elements you are looking for, rather than what you are not looking for (which is anyway an open-ended list when plugins can contribute API elements). The value provided to tree should be a list of property names to include, with subproperties inside square braces. For example:

http://127.0.0.1:8080/api/xml?tree=jobs[name],views[name,jobs[name]]

Will show just a list of jobs (only giving the name) and views (giving the name and jobs they contain).

Note: for array-type properties (such as jobs in this example), the name must be given in the original plural, not in the singular as the element would appear in XML ( <job>).

This will be more natural for e.g. json?tree=jobs[name] anyway as the JSON writer does not do plural-to-singular mangling because arrays are represented explicitly.

Detecting Hudson version

To check the version of Hudson, load the top page and check for the "X-Hudson" response header. This contains the version number of Hudson, like "3.0.0" This is also a good way to check if an URL is a Hudson URL.

Discovering Hudson on the Network

Hudson instances listen on UDP port 33848. Whenever a UDP packet is received, it will respond with a short XML fragment that shows the connection information. This XML has the following format:

<hudson> 
  <version>3.0.0</version>           <!-- version of Hudson -->
 <url>http://somwhere/hudson/</url>  <!-- HTTP URL. Not available if not configured -->
 <slave-port>12345</slave-port>      <!-- if TCP slave listener port is configured, its number -->
</hudson> 

By using this, a client can use a UDP broadcast to try to discover nearby Hudson instances. This is primarily useful for a self-organizing build cluster.