All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.offbytwo.jenkins.JenkinsServer Maven / Gradle / Ivy

There is a newer version: 0.3.8
Show newest version
/*
 * Copyright (c) 2013 Rising Oak LLC.
 *
 * Distributed under the MIT license: http://opensource.org/licenses/MIT
 */

package com.offbytwo.jenkins;

import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.google.common.net.UrlEscapers;
import com.offbytwo.jenkins.client.JenkinsHttpClient;
import com.offbytwo.jenkins.model.Build;
import com.offbytwo.jenkins.model.Computer;
import com.offbytwo.jenkins.model.ComputerSet;
import com.offbytwo.jenkins.model.Job;
import com.offbytwo.jenkins.model.JobConfiguration;
import com.offbytwo.jenkins.model.JobWithDetails;
import com.offbytwo.jenkins.model.LabelWithDetails;
import com.offbytwo.jenkins.model.MainView;
import com.offbytwo.jenkins.model.MavenJobWithDetails;
import com.offbytwo.jenkins.model.QueueItem;
import com.offbytwo.jenkins.model.QueueReference;
import com.offbytwo.jenkins.model.View;

import org.apache.http.client.HttpResponseException;
import org.apache.http.entity.ContentType;
import org.dom4j.DocumentException;

import javax.xml.bind.JAXBException;

import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;

/**
 * The main starting point for interacting with a Jenkins server.
 */
public class JenkinsServer {

    private final JenkinsHttpClient client;

    /**
     * Create a new Jenkins server reference given only the server address
     *
     * @param serverUri
     *            address of jenkins server (ex. http://localhost:8080/jenkins)
     */
    public JenkinsServer(URI serverUri) {
        this(new JenkinsHttpClient(serverUri));
    }

    /**
     * Create a new Jenkins server reference given the address and credentials
     *
     * @param serverUri
     *            address of jenkins server (ex. http://localhost:8080/jenkins)
     * @param username
     *            username to use when connecting
     * @param passwordOrToken
     *            password (not recommended) or token (recommended)
     */
    public JenkinsServer(URI serverUri, String username, String passwordOrToken) {
        this(new JenkinsHttpClient(serverUri, username, passwordOrToken));
    }

    /**
     * Create a new Jenkins server directly from an HTTP client (ADVANCED)
     *
     * @param client
     *            Specialized client to use.
     */
    public JenkinsServer(JenkinsHttpClient client) {
        this.client = client;
    }

    /**
     * Get the current status of the Jenkins end-point by pinging it.
     *
     * @return true if Jenkins is up and running, false otherwise
     */
    public boolean isRunning() {
        try {
            client.get("/");
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * Get a list of all the defined jobs on the server (at the summary level)
     *
     * @return list of defined jobs (summary level, for details @see Job#details
     * @throws IOException
     */
    public Map getJobs() throws IOException {
        List jobs = client.get("/", MainView.class).getJobs();
        return Maps.uniqueIndex(jobs, new Function() {
            @Override
            public String apply(Job job) {
                job.setClient(client);
                return job.getName().toLowerCase();
            }
        });
    }

    /**
     * Get a list of all the defined views on the server (at the summary level)
     *
     * @return list of defined views
     * @throws IOException
     */
    public Map getViews() throws IOException {
        List views = client.get("/", MainView.class).getViews();
        return Maps.uniqueIndex(views, new Function() {
            @Override
            public String apply(View view) {
                view.setClient(client);
                // return view.getName().toLowerCase();
                return view.getName();
            }
        });
    }

    /**
     * Get a single view object from the server
     *
     * @param name
     *            name of the view in Jenkins
     * @return the view object
     * @throws IOException
     */
    public View getView(String name) throws IOException {
        return client.get("/view/" + encode(name) + "/", View.class);
    }

    /**
     * Get a list of all the defined jobs on the server (at the specified view
     * level)
     *
     * @return list of defined jobs (view level, for details @see Job#details
     * @throws IOException
     */
    public Map getJobs(String view) throws IOException {
        List jobs = client.get("/view/" + encode(view) + "/", View.class).getJobs();
        return Maps.uniqueIndex(jobs, new Function() {
            @Override
            public String apply(Job job) {
                job.setClient(client);
                return job.getName().toLowerCase();
            }
        });
    }

    /**
     * Get a single Job from the server.
     *
     * @return A single Job, null if not present
     * @throws IOException
     */
    public JobWithDetails getJob(String jobName) throws IOException {
        try {
            JobWithDetails job = client.get("/job/" + encode(jobName), JobWithDetails.class);
            job.setClient(client);

            return job;
        } catch (HttpResponseException e) {
            if (e.getStatusCode() == 404) {
                return null;
            }
            throw e;
        }

    }

    public MavenJobWithDetails getMavenJob(String jobName) throws IOException {
        try {
            MavenJobWithDetails job = client.get("/job/" + encode(jobName), MavenJobWithDetails.class);
            job.setClient(client);

            return job;
        } catch (HttpResponseException e) {
            if (e.getStatusCode() == 404) {
                return null;
            }
            throw e;
        }
    }

    /**
     * Create a job on the server using the provided xml
     *
     * @return the new job object
     * @throws IOException
     */
    public void createJob(String jobName, String jobXml) throws IOException {
        client.post_xml("/createItem?name=" + encodeParam(jobName), jobXml);
    }

    public void createJob(String jobName, String jobXml, Boolean crumbFlag) throws IOException {
        client.post_xml("/createItem?name=" + encodeParam(jobName), jobXml, crumbFlag);
    }

    /**
     * Get the xml description of an existing job
     *
     * @return the new job object
     * @throws IOException
     */
    public String getJobXml(String jobName) throws IOException {
        return client.get("/job/" + encode(jobName) + "/config.xml");
    }

    /**
     * Get the description of an existing Label
     *
     * @return label object
     * @throws IOException
     */
    public LabelWithDetails getLabel(String labelName) throws IOException {
        return client.get("/label/" + encode(labelName), LabelWithDetails.class);
    }

    /**
     * Get a list of all the computers on the server (at the summary level)
     *
     * @return list of defined computers (summary level, for details @see
     *         Computer#details
     * @throws IOException
     */
    public Map getComputers() throws IOException {
        List computers = client.get("computer/", Computer.class).getComputers();
        return Maps.uniqueIndex(computers, new Function() {
            @Override
            public String apply(Computer computer) {
                computer.setClient(client);
                return computer.getDisplayName().toLowerCase();
            }
        });
    }

    /**
     * The ComputerSet class will give informations
     * like {@link ComputerSet#getBusyExecutors()} or
     * the {@link ComputerSet#getTotalExecutors()}.
     * 
     * @return {@link ComputerSet}
     * @throws IOException
     */
    public ComputerSet getComputerSet() throws IOException {
        return client.get("computer/", ComputerSet.class);
    }

    /**
     * Update the xml description of an existing job
     *
     * @return the new job object
     * @throws IOException
     */
    public void updateJob(String jobName, String jobXml) throws IOException {
        this.updateJob(jobName, jobXml, true);
    }

    public void updateJob(String jobName, String jobXml, boolean crumbFlag) throws IOException {
        client.post_xml("/job/" + encode(jobName) + "/config.xml", jobXml, crumbFlag);
    }

    public void addStringParam(String jobName, String name, String description, String defaultValue)
            throws IOException, JAXBException, DocumentException {
        String jobXml = this.getJobXml(jobName);
        JobConfiguration jobConf = new JobConfiguration(jobXml);
        jobXml = jobConf.addStringParam(name, description, defaultValue).asXml();
        this.updateJob(jobName, jobXml);
    }

    /**
     * Sends the Quiet Down (Prepare for shutdown) message
     * 
     * @throws IOException
     */
    public void quietDown() throws IOException {
        try {
            client.get("/quietDown/");
        } catch (org.apache.http.client.ClientProtocolException e) {
            e.printStackTrace();
        }

    }

    /**
     * Cancels the Quiet Down (Prepare for shutdown) message
     * 
     * @throws IOException
     */
    public void cancelQuietDown() throws IOException {
        try {
            client.post("/cancelQuietDown/");
        } catch (org.apache.http.client.ClientProtocolException e) {
            e.printStackTrace();
        }
    }

    /*
     * Delete a job from jenkins
     *
     * @throws IOException
     */
    public void deleteJob(String jobName) throws IOException {
        client.post("/job/" + encode(jobName) + "/doDelete");
    }

    /**
     * Delete a job from Jenkins.
     * 
     * @param jobName
     *            The name of the job to be deleted.
     * @param crumbFlag
     *            The crumFlag.
     * @throws IOException
     *             In case of an failure.
     */
    public void deleteJob(String jobName, boolean crumbFlag) throws IOException {
        client.post("/job/" + encode(jobName) + "/doDelete", crumbFlag);
    }

    /**
     * Runs the provided groovy script on the server and returns the result.
     *
     * This is similar to running groovy scripts using the script console.
     *
     * In the instance where your script causes an exception, the server still
     * returns a 200 status, so detecting errors is very challenging. It is
     * recommended to use heuristics to check your return string for stack
     * traces by detecting strings like "groovy.lang.(something)Exception".
     *
     * @param script
     * @return results
     * @throws IOException
     */
    public String runScript(String script) throws IOException {
        return client.post_text("/scriptText", "script=" + script, ContentType.APPLICATION_FORM_URLENCODED, false);
    }

    private String encode(String pathPart) {
        // jenkins doesn't like the + for space, use %20 instead
        String escape = UrlEscapers.urlPathSegmentEscaper().escape(pathPart);
        return escape;
    }

    private String encodeParam(String pathPart) {
        // jenkins doesn't like the + for space, use %20 instead
        return UrlEscapers.urlFormParameterEscaper().escape(pathPart);
    }

    public QueueItem getQueueItem(QueueReference ref) throws IOException 
    {
      try {
        String url = ref.getQueueItemUrlPart();
        // "/queue/item/" + id
        QueueItem job = client.get(url , QueueItem.class);
        job.setClient(client);

        return job;
      } catch (HttpResponseException e) {
          if (e.getStatusCode() == 404) {
              return null;
          }
          throw e;
      }      
    }

    public Build getBuild(QueueItem q)  throws IOException 
    {
      // http://ci.seitenbau.net/job/rainer-ansible-build/51/
      try {
        String url = q.getExecutable().getUrl();
        // "/queue/item/" + id
        Build job = client.get(url , Build.class);
        job.setClient(client);

        return job;
      } catch (HttpResponseException e) {
          if (e.getStatusCode() == 404) {
              return null;
          }
          throw e;
      }      
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy