Code Monkey home page Code Monkey logo

jenkins_api_client's Introduction

Jenkins API Client

Gem Version Build Status Dependency Status Code Climate

Copyright © 2012-2017, Kannan Manickam endorse

Client libraries for communicating with a Jenkins CI server and programatically managing jobs.

IRC Channel: ##jenkins-api-client (on freenode)

Mailing list: [email protected]

Google Group: https://groups.google.com/group/jenkins_api_client

OVERVIEW:

This project is a simple API client for interacting with Jenkins Continuous Integration server. Jenkins provides three kinds of remote access API.

  1. XML API, 2. JSON API, and 3. Python API. This project aims at consuming the JSON API and provides some useful functions for controlling jobs on the Jenkins programatically. Even though Jenkins provides an awesome UI for controlling jobs, it would be nice and helpful to have a programmable interface so we can dynamically and automatically manage jobs and other artifacts.

DETAILS:

This project currently only provides functionality for the jobs, node, view, system, and build queue interfaces.

USAGE:

Installation

Install jenkins_api_client by sudo gem install jenkins_api_client. Include this gem in your code as a require statement.

require 'jenkins_api_client'

Using with IRB

If you want to just play with it and not actually write a script, you can just use the irb launcher script which is available in scripts/login_with_irb.rb. But make sure that you have your credentials available in the correct location. By default the script assumes that you have your credentials file in ~/.jenkins_api_client/login.yml. If you don't prefer this location and would like to use a different location, just modify that script to point to the location where the credentials file exists.

ruby scripts/login_with_irb.rb

You will see that it entered IRB session and you can play with the API client with the @client object that it has returned.

Authentication

Supplying credentials to the client is optional, as not all Jenkins instances require authentication. This project supports two types of password-based authentication. You can just use the plain password by using password parameter. If you don't prefer leaving plain passwords in the credentials file, you can encode your password in base64 format and use password_base64 parameter to specify the password either in the arguments or in the credentials file. To use the client without credentials, just leave out the username and password parameters. The password parameter is only required if username is specified.

Using with Open ID

It is very simple to authenticate with a Jenkins server that has Open ID authentication enabled. You will have to obtain your API token and use the API token as the password. To obtain the API token, go to your user configuration page and click 'Show API Token'. Use this token for the password parameter when initializing the client.

Cross-site Scripting (XSS) and Crumb Support

Support for Jenkins crumbs has been added. These allow an application to use the Jenkins API POST methods without requiring the 'Prevent Cross Site Request Forgery exploits' to be disabled. The API will check in with the Jenkins server to determine whether crumbs are enabled or not, and use them if appropriate.

SSL certificate verification

When connecting over HTTPS, if the server's certificate is not trusted, the connection will be aborted. To trust a certificate, specify the ca_file parameter when creating the client. The value should be a path to a PEM encoded file containing the certificates.

Basic Usage

As discussed earlier, you can either specify all the credentials and server information as parameters to the Client or have a credentials file and just parse the yaml file and pass it in. The following call just passes the information as parameters

@client = JenkinsApi::Client.new(:server_ip => '0.0.0.0',
         :username => 'somename', :password => 'secret password')
# The following call will return all jobs matching 'Testjob'
puts @client.job.list("^Testjob")

The following example passes the YAML file contents. An example yaml file is located in config/login.yml.example.

@client = JenkinsApi::Client.new(YAML.load_file(File.expand_path(
  "~/.jenkins_api_client/login.yml", __FILE__)))
# The following call lists all jobs
puts @client.job.list_all

Chaining and Building Jobs

Sometimes we want certain jobs to be added as downstream projects and run them sequentially. The following example will explain how this could be done.

require 'jenkins_api_client'

# We want to filter all jobs that start with 'test_job'
# Just write a regex to match all the jobs that start with 'test_job'
jobs_to_filter = "^test_job.*"

# Create an instance to jenkins_api_client
@client = JenkinsApi::Client.new(YAML.load_file(File.expand_path(
  "~/.jenkins_api_client/login.yml", __FILE__)))

# Get a filtered list of jobs from the server
jobs = @client.job.list(jobs_to_filter)

# Chain all the jobs with 'success' as the threshold
# The chain method will return the jobs that is in the head of the sequence
# This method will also remove any existing chaining
initial_jobs = @client.job.chain(jobs, 'success', ["all"])

# Now that we have the initial job(s) we can build them
# The build function returns a code from the API which should be 201 if
# the build was successful, for Jenkins >= v1.519
# For versions older than v1.519, the success code is 302.
code = @client.job.build(initial_jobs[0])
raise "Could not build the job specified" unless code == '201'

In the above example, you might have noticed that the chain method returns an array instead of a single job. There is a reason behind it. In simple chain, such as the one in the example above, all jobs specified are chained one by one. But in some cases they might not be dependent on the previous jobs and we might want to run some jobs parallelly. We just have to specify that as a parameter.

For example: parallel = 3 in the parameter list to the chain method will take the first three jobs and chain them with the next three jobs and so forth till it reaches the end of the list.

There is another filter option you can specify for the method to take only jobs that are in a particular state. In case if we want to build only jobs that are failed or unstable, we can achieve that by passing in the states in the third parameter. In the example above, we wanted to build all jobs. If we just want to build failed and unstable jobs, just pass ["failure", "unstable"]. Also if you pass in an empty array, it will assume that you want to consider all jobs and no filtering will be performed.

There is another parameter called threshold you can specify for the chaining and this is used to decide whether to move forward with the next job in the chain or not. A success will move to the next job only if the current build succeeds, failure will move to the next job even if the build fails, and unstable will move to the job even if the build is unstable.

The following call to the chain method will consider only failed and unstable jobs, chain then with 'failure' as the threshold, and also chain three jobs in parallel.

initial_jobs = @client.job.chain(jobs, 'failure', ["failure", "unstable"], 3)
# We will receive three jobs as a result and we can build them all
initial_jobs.each do |job|
  code = @client.job.build(job)
  raise "Unable to build job: #{job}" unless code == '201'
end

Configuring plugins

Given the abundance of plugins for Jenkins, we now provide a extensible way to set up jobs and configure their plugins. Right now, the gem ships with the hipchat plugin, with more plugins to follow in the future.

hipchat_settings = JenkinsApi::Client::PluginSettings::Hipchat.new({
  :room => '10000',
  :start_notification => true,
  :notify_success => true,
  :notify_aborted => true,
  :notify_not_built => true,
  :notify_unstable => true,
  :notify_failure => true,
  :notify_back_to_normal => true,
})

client = JenkinsApi::Client.new(
  server_url: jenkins_server,
  username: username,
  password: password
)

# NOTE: plugins can be splatted so if you had another plugin it could be passed
# to the new call below as another arg after hipchat
job = JenkinsApi::Client::Job.new(client, hipchat)

Writing your own plugins is also straightforward. Inherit from the JenkinsApi::Client::PluginSettings::Base class and override the configure method. Jenkins jobs are configured using xml so you just need to figure out where in the configuration to hook in your plugin settings.

Here is an example of a plugin written to configure a job for workspace cleanup.

module JenkinsApi
  class Client
    module PluginSettings
      class WorkspaceCleanup < Base

        # @option params [Boolean] :delete_dirs (false)
        #   whether to also apply pattern on directories
        # @option params [String] :cleanup_parameters
        # @option params [String] :external_delete
        def initialize(params={})
          @params = params
        end

        # Create or Update a job with params given as a hash instead of the xml
        # This gives some flexibility for creating/updating simple jobs so the
        # user doesn't have to learn about handling xml.
        #
        # @param xml_doc [Nokogiri::XML::Document] xml document to be updated with 
        # the plugin configuration
        #
        # @return [Nokogiri::XML::Document]
        def configure(xml_doc)
          xml_doc.tap do |doc|
            Nokogiri::XML::Builder.with(doc.at('buildWrappers')) do |build_wrappers|
              build_wrappers.send('hudson.plugins.ws__cleanup.PreBuildCleanup') do |x|
                x.deleteDirs @params.fetch(:delete_dirs) { false }
                x.cleanupParameter @params.fetch(:cleanup_parameter) { '' }
                x.externalDelete @params.fetch(:external_delete) { '' }
              end
            end
          end
        end
      end
    end
  end
end

Currently, the skype plugin is still configured directly on the jenkins job. This will likely be extracted into its own plugin in the near future, but we will maintain backwards compatibility until after an official deprecation period.

Waiting for a build to start/Getting the build number

Newer versions of Jenkins (starting with the 1.519 build) make it easier for an application to determine the build number for a 'build' request. (previously there would be a degree of guesswork involved). The new version actually returns information allowing the jenkins_api_client to check the build queue for the job and see if it has started yet (once it has started, the build- number is available.

If you wish to take advantage of this hands-off approach, the build method supports an additional 'opts' hash that lets you specify how long you wish to wait for the build to start.

Old Jenkins vs New Jenkins (1.519+)

Old (v < 1.519)

The 'opts' parameter will work with older versions of Jenkins with the following caveats:

  • The 'cancel_on_build_start_timeout' option has no effect
  • The build_number is calculated by calling 'current_build_number' and adding 1 before the build is started. This might break if there are multiple entities running builds on the same job, or there are queued builds.
New (v >= 1.519)
  • All options work, and build number is accurately determined from queue info.
  • The build trigger success code is now 201 (Created). Previously it was 302.

Initiating a build and returning the build_number

Minimum required
# Minimum options required
opts = {'build_start_timeout' => 30}
@client.job.build(job_name, job_params || {}, opts)

This method will block for up to 30 seconds, while waiting for the build to start. Instead of returning an http-status code, it will return the build_number, or if the build has not started will raise 'Timeout::Error' Note: to maintain legacy compatibility, passing 'true' will set the timeout to the default timeout specified when creating the @client.

Auto cancel the queued-build on timeout
# Wait for up to 30 seconds, attempt to cancel queued build
opts = {'build_start_timeout' => 30,
        'cancel_on_build_start_timeout' => true}
@client.job.build(job_name, job_params || {}, opts)

This method will block for up to 30 seconds, while waiting for the build to start. Instead of returning an http-status code, it will return the build_number, or if the build has not started will raise 'Timeout::Error'. Prior to raising the Timeout::Error, it will attempt to cancel the queued build - thus preventing it from starting.

Getting some feedback while you're waiting

The opts parameter supports two values that can be assigned proc objects (which will be 'call'ed). Both are optional, and will only be called if specified in opts. These are initially intended to assist with logging progress.

  • 'progress_proc' - called when job is initially queued, and periodically thereafter.
    • max_wait - the value of 'build_start_timeout'
    • current_wait - how long we've been waiting so far
    • poll_count - how many times we've polled the queue
  • 'completion_proc' - called just prior to return/Timeout::Error
    • build_number - the build number assigned (or nil if timeout)
    • cancelled - whether the build was cancelled (true if 'new' Jenkins and it was able to cancel the build, false otherwise)

To use a class method, just specify 'instance.method(:method_name)', or use a proc or lambda

# Wait for up to 30 seconds, attempt to cancel queued build, progress
opts = {'build_start_timeout' => 30,
        'cancel_on_build_start_timeout' => true,
        'poll_interval' => 2,      # 2 is actually the default :)
        'progress_proc' => lambda {|max,curr,count| ... },
        'completion_proc' => lambda {|build_number,cancelled| ... }}
@client.job.build(job_name, job_params || {}, opts)

Running Jenkins CLI

To running Jenkins CLI

  • authentication with username/password (deprecated)
@client = JenkinsApi::Client.new(:server_ip => '127.0.0.1',
         :username => 'somename', :password => 'secret password')
# The following call will return the version of Jenkins instance
puts @client.exec_cli("version")
  • authentication with public/private key file remember to upload the public key to:

    http://#{Server IP}:#{Server Port}/user/#{Username}/configure

@client = JenkinsApi::Client.new(:server_ip => '127.0.0.1',
         :identity_file => '~/.ssh/id_rsa')
# The following call will return the version of Jenkins instance
puts @client.exec_cli("version")

Before you run the CLI, please make sure the following requirements are fulfilled:

  • JRE/JDK 6 (or above) is installed, and 'java' is on the $PATH environment variable
  • The jenkins_api_client/java_deps/jenkins-cli.jar is required as the client to run the CLI. You can retrieve the available commands via accessing the URL: http://<server>:<port>/cli
  • (Optional) required if you run the Groovy Script through CLI; make sure the user has the privilige to run script

Using with command line

Command line interface is supported only from version 0.2.0. See help using jenkinscli help

There are three ways for authentication using command line interface

  1. Passing all credentials and server information using command line parameters
  2. Passing the credentials file as the command line parameter
  3. Having the credentials file in the default location HOME/.jenkins_api_client/login.yml

Debug

As of v0.13.0, this debug parameter is removed. Use the logger instead. See the next section for more information about this option.

Logger

As of v0.13.0, support for logger is introduced. Since it would be nice to have the activities of the jenkins_api_client in a log file, this feature is implemented using the Ruby's standard Logger class. For using this feature, there are two new input arguments used during the initialization of Client.

  1. :log_location - This argument specifies the location for the log file. A good location for linux based systems would be '/var/log/jenkins_api_client.log'. The default for this values is STDOUT. This will print the log messages on the console itself.
  2. :log_level - This argument specifies the level of messages to be logged. It should be one of Logger::DEBUG (0), Logger::INFO (1), Logger::WARN (2), Logger::ERROR (3), Logger::FATAL (4). It can be specified either using the constants available in the Logger class or using these integers provided here. The default for this argument is Logger::INFO (1)

If you want customization on the functionality Logger provides, such as leave n old log files, open the log file in append mode, create your own logger and then set that in the client.

Examples

  @client = JenkinsApi::Client.new(...)
  # Create a logger which ages logfile once it reaches a certain size. Leave 10
  # “old log files” and each file is about 1,024,000 bytes.
  @client.logger = Logger.new('foo.log', 10, 1024000)

Please refer to Ruby Logger for more information.

CONTRIBUTING:

If you would like to contribute to this project, just do the following:

  1. Fork the repo on Github.
  2. Add your features and make commits to your forked repo.
  3. Make a pull request to this repo.
  4. Review will be done and changes will be requested.
  5. Once changes are done or no changes are required, pull request will be merged.
  6. The next release will have your changes in it.

Please take a look at the issues page if you want to get started.

FEATURE REQUEST:

If you use this gem for your project and you think it would be nice to have a particular feature that is presently not implemented, I would love to hear that and consider working on it. Just open an issue in GitHub as a feature request.

jenkins_api_client's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jenkins_api_client's Issues

chain function does a nested unchain, creates dependency on order or execution.

The chain function calls the unchain function. This creates a dependency on the order for adding jobs.

for clarity I'll write down what the jobs look like in jenkins (jobs pointing to downstream jobs like A->B meaning A has downstream job B)

For example, this order works.
-create a job list [ A, B, C]
-chain the job list [A, B, C] so now jenkins has A->B->C
-iterate through job array [A,B,C] and respectively add downstream jobs a, b, c. Result is this... A->B,a B->C,b C

While this order does not work
-create job list [A, B, C]
-iterate through job array and add downstream jobs respectively. Now jenkins has this A->a B->b C->c
-chain job array [A,B,C]. Now jenkins has this A->B->C The jobs a, b and c are no longer downstream jobs because they were unchained.

Because chain will 'unchain' the jobs, the downstream jobs added in the second scenario will be lost.

Removing the nested unchain means higher level scripts would have to do this, but that may be ok as it will be more clear, and also make it more flexible.

Linking job fails, unable to detect out sync jenkins configuration.

When setting up and running some jobs I ran into this problem.

  • A series of jobs were created and loaded into jenkins.
  • Some review was done on the jobs, and one was designated as 'not needed' so it was deleted from the hard drive out from under Jenkins.
  • Jenkins however, still reports the job as existing and will reply as valid job to most calls.
  • however, when running a script to link jobs together, that job came up to link , (because the jenkins api still reported it as a valid job), and then it reached for the hard drive, at which point it could not find the config.xml file.
  • the root of the problem is in the out of sync configuration in jenkins, however we can probably add some handling in cases where we don't find the config xml so we exit cleanly or with a clearer error message.

Mapping of 'gray' status to 'not run' includes space. Can be a problem in command line use.

I'm creating a command line tool based on your jenkins_api_client. I'm using optparse to pass in the values of which jobs to build or not build. The command line flag looks like this "--filter failed,aborted", but when including the 'not run' jobs one must be careful to enclose in quotes or else this wont work (--filter failed,not run,aborted doesn't work, but this does.... --filter failed,"not run",aborted.)

Minor request, change "not run" to not_run, that would make command line more uniform.

Thanks!

Reduce complexity of create_freestyle method

The create_freestyle method is a huge method that builds the job config xml based on the input parameters. It can be split into multiple methods to create portion of xml and thus can be reused when adding other project types.

Add functionality to rename a job in Jenkins.

I just noticed a feature in the Jenkins UI that if you change the name of a job, it gives an option for that job's name to be renamed. This can be easily implemented through the API.

class JenkinsApi::Client::Job
  def rename(old_job, new_job)
    # Obtain the configuration of the old job
    xml = get_config(old_job)
    # Create the new job before deleting the old job
    create(new_job, xml)
    # Now delete the old job
    delete(old_job)
  end
end

As usual, test cases should be added for both unit and functional tests.

Client arguments

Question is more generic I think. The client accepts a number of arguments. What is expected for those. For example ssl and debug. Is true/false or string of some sort.

get_eta in BuildQueue doesn't differentiate between task not found and ETA not found

In the following code in lib/jenkins_api_client/build_queue.rb

def get_eta(task_name)
  eta = nil
  details = get_details(task_name)
  unless details.empty?
    matched = details["why"].match(/.*\(ETA:(.*)\)/)
    eta = matched[1].strip unless matched.nil?
  end
  eta
end

The ETA is not available for all tasks. It is available in the API only if Jenkins had run the same job previously and can estimate the running time of the Job's previous build. It returns nil for both cases. Returning nil for the task not found makes sense. But it the regex is not matched (i.e.) ETA is not available, it can return N/A instead of nil.

105 failing tests on ruby 1.9.3/os-x

$ ruby -v
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin12.2.0]

$ bundle
$ rake test
...
233 examples, 105 failures

Failed examples:

rspec ./spec/func_tests/client_spec.rb:31 # JenkinsApi::Client Given valid credentials and server information are given InstanceMethods #debug Should be able to toggle the debug value
rspec ./spec/func_tests/client_spec.rb:38 # JenkinsApi::Client Given valid credentials and server information are given InstanceMethods #initialize Should be able to initialize with valid credentials
rspec ./spec/func_tests/client_spec.rb:45 # JenkinsApi::Client Given valid credentials and server information are given InstanceMethods #initialize Should accept a YAML argument when creating a new client
rspec ./spec/func_tests/client_spec.rb:52 # JenkinsApi::Client Given valid credentials and server information are given InstanceMethods #initialize Should fail if wrong credentials are given
rspec ./spec/func_tests/client_spec.rb:64 # JenkinsApi::Client Given valid credentials and server information are given InstanceMethods #get_jenkins_version Should the jenkins version
rspec ./spec/func_tests/client_spec.rb:70 # JenkinsApi::Client Given valid credentials and server information are given InstanceMethods #get_hudson_version Should get the hudson version
rspec ./spec/func_tests/client_spec.rb:76 # JenkinsApi::Client Given valid credentials and server information are given InstanceMethods #get_server_date Should return the server date
rspec ./spec/func_tests/client_spec.rb:84 # JenkinsApi::Client Given valid credentials and server information are given SubClassAccessorMethods #job Should return a job object on call
rspec ./spec/func_tests/client_spec.rb:90 # JenkinsApi::Client Given valid credentials and server information are given SubClassAccessorMethods #node Should return a node object on call
rspec ./spec/func_tests/client_spec.rb:96 # JenkinsApi::Client Given valid credentials and server information are given SubClassAccessorMethods #view Should return a view object on call
rspec ./spec/func_tests/client_spec.rb:102 # JenkinsApi::Client Given valid credentials and server information are given SubClassAccessorMethods #system Should return a system object on call
rspec ./spec/func_tests/client_spec.rb:108 # JenkinsApi::Client Given valid credentials and server information are given SubClassAccessorMethods #queue Should return a build queue object on call
rspec ./spec/func_tests/job_spec.rb:54 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create Should be able to create a job by getting an xml
rspec ./spec/func_tests/job_spec.rb:71 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should be able to create a simple freestyle job
rspec ./spec/func_tests/job_spec.rb:78 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should be able to create a freestyle job with shell command
rspec ./spec/func_tests/job_spec.rb:86 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept Git SCM provider
rspec ./spec/func_tests/job_spec.rb:96 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept subversion SCM provider
rspec ./spec/func_tests/job_spec.rb:106 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept CVS SCM provider with branch
rspec ./spec/func_tests/job_spec.rb:117 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept CVS SCM provider with tag
rspec ./spec/func_tests/job_spec.rb:140 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept restricted_node option
rspec ./spec/func_tests/job_spec.rb:148 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept block_build_when_downstream_building option
rspec ./spec/func_tests/job_spec.rb:156 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept block_build_when_upstream_building option
rspec ./spec/func_tests/job_spec.rb:164 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept concurrent_build option
rspec ./spec/func_tests/job_spec.rb:172 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept the timer option
rspec ./spec/func_tests/job_spec.rb:180 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept child projects option
rspec ./spec/func_tests/job_spec.rb:189 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept notification_email option
rspec ./spec/func_tests/job_spec.rb:197 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept notification for individual skype targets
rspec ./spec/func_tests/job_spec.rb:205 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept notification for group skype targets
rspec ./spec/func_tests/job_spec.rb:213 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #create_freestyle Should accept complex skype configuration
rspec ./spec/func_tests/job_spec.rb:231 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #add_email_notification Should accept email address and add to existing job
rspec ./spec/func_tests/job_spec.rb:244 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #add_skype_notification Should accept skype configuration and add to existing job
rspec ./spec/func_tests/job_spec.rb:257 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #rename Should accept new and old job names and rename the job
rspec ./spec/func_tests/job_spec.rb:270 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #recreate Should be able to re-create a job
rspec ./spec/func_tests/job_spec.rb:276 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #change_description Should be able to change the description of a job
rspec ./spec/func_tests/job_spec.rb:284 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #delete Should be able to delete a job
rspec ./spec/func_tests/job_spec.rb:290 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #list_all Should list all jobs
rspec ./spec/func_tests/job_spec.rb:296 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #list Should return job names based on the filter
rspec ./spec/func_tests/job_spec.rb:306 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #list_by_status Should be able to list jobs by status
rspec ./spec/func_tests/job_spec.rb:317 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #list_all_with_details Should return all job names with details
rspec ./spec/func_tests/job_spec.rb:323 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #list_details Should list details of a particular job
rspec ./spec/func_tests/job_spec.rb:331 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #get_upstream_projects Should list upstream projects of the specified job
rspec ./spec/func_tests/job_spec.rb:337 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #get_downstream_projects Should list downstream projects of the specified job
rspec ./spec/func_tests/job_spec.rb:343 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #get_builds Should get builds of a specified job
rspec ./spec/func_tests/job_spec.rb:349 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #get_current_build_status Should obtain the current build status for the specified job
rspec ./spec/func_tests/job_spec.rb:365 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #build Should build the specified job
rspec ./spec/func_tests/job_spec.rb:383 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #stop Should be able to abort a recent build of a running job
rspec ./spec/func_tests/job_spec.rb:398 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #restrict_to_node Should be able to restrict a job to a node
rspec ./spec/func_tests/job_spec.rb:406 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #chain Should be able to chain all jobs
rspec ./spec/func_tests/job_spec.rb:414 # JenkinsApi::Client::Job With properly initialized client InstanceMethods #chain Should be able to chain jobs based on the specified criteria
rspec ./spec/func_tests/node_spec.rb:33 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #initialize Initializes without any exception
rspec ./spec/func_tests/node_spec.rb:38 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #initialize Raises an error if a reference of client is not passed
rspec ./spec/func_tests/node_spec.rb:55 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #create_dump_slave accepts required params and creates the slave on jenkins
rspec ./spec/func_tests/node_spec.rb:63 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #create_dump_slave accepts spaces and other characters in node name
rspec ./spec/func_tests/node_spec.rb:71 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #create_dump_slave fails if name is missing
rspec ./spec/func_tests/node_spec.rb:80 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #create_dump_slave fails if slave_host is missing
rspec ./spec/func_tests/node_spec.rb:89 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #create_dump_slave fails if private_key_file is missing
rspec ./spec/func_tests/node_spec.rb:98 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #create_dump_slave fails if the slave already exists in Jenkins
rspec ./spec/func_tests/node_spec.rb:113 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #delete deletes the node given the name
rspec ./spec/func_tests/node_spec.rb:122 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #delete raises an error if the slave doesn't exist in Jenkins
rspec ./spec/func_tests/node_spec.rb:130 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #list Should be able to list all nodes
rspec ./spec/func_tests/node_spec.rb:139 # JenkinsApi::Client::Node With properly initialized client InstanceMethods GeneralAttributes #get_busyExecutors should get the busyExecutors attribute
rspec ./spec/func_tests/node_spec.rb:139 # JenkinsApi::Client::Node With properly initialized client InstanceMethods GeneralAttributes #get_displayName should get the displayName attribute
rspec ./spec/func_tests/node_spec.rb:139 # JenkinsApi::Client::Node With properly initialized client InstanceMethods GeneralAttributes #get_totalExecutors should get the totalExecutors attribute
rspec ./spec/func_tests/node_spec.rb:150 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeProperties #is_idle should get the idle property
rspec ./spec/func_tests/node_spec.rb:150 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeProperties #is_jnlpAgent should get the jnlpAgent property
rspec ./spec/func_tests/node_spec.rb:150 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeProperties #is_launchSupported should get the launchSupported property
rspec ./spec/func_tests/node_spec.rb:150 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeProperties #is_manualLaunchAllowed should get the manualLaunchAllowed property
rspec ./spec/func_tests/node_spec.rb:150 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeProperties #is_offline should get the offline property
rspec ./spec/func_tests/node_spec.rb:150 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeProperties #is_temporarilyOffline should get the temporarilyOffline property
rspec ./spec/func_tests/node_spec.rb:161 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeAttributes #get_node_numExecutors Should be able to list all node attributes
rspec ./spec/func_tests/node_spec.rb:161 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeAttributes #get_node_icon Should be able to list all node attributes
rspec ./spec/func_tests/node_spec.rb:161 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeAttributes #get_node_displayName Should be able to list all node attributes
rspec ./spec/func_tests/node_spec.rb:161 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeAttributes #get_node_loadStatistics Should be able to list all node attributes
rspec ./spec/func_tests/node_spec.rb:161 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeAttributes #get_node_monitorData Should be able to list all node attributes
rspec ./spec/func_tests/node_spec.rb:161 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeAttributes #get_node_offlineCause Should be able to list all node attributes
rspec ./spec/func_tests/node_spec.rb:161 # JenkinsApi::Client::Node With properly initialized client InstanceMethods NodeAttributes #get_node_oneOffExecutors Should be able to list all node attributes
rspec ./spec/func_tests/node_spec.rb:169 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #change_mode changes the mode of the given slave to the given mode
rspec ./spec/func_tests/node_spec.rb:176 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #get_config obtaines the node config.xml from the server
rspec ./spec/func_tests/node_spec.rb:184 # JenkinsApi::Client::Node With properly initialized client InstanceMethods #post_config posts the given config.xml to the jenkins server's node
rspec ./spec/func_tests/system_spec.rb:24 # JenkinsApi::Client::System With properly initialized client InstanceMethods #quiet_down Should be able to quiet down a Jenkins server
rspec ./spec/func_tests/system_spec.rb:30 # JenkinsApi::Client::System With properly initialized client InstanceMethods #cancel_quiet_down Should be able to cancel the quiet down a Jenkins server
rspec ./spec/func_tests/system_spec.rb:36 # JenkinsApi::Client::System With properly initialized client InstanceMethods #restart Should be able to restart a Jenkins server safely
rspec ./spec/func_tests/system_spec.rb:40 # JenkinsApi::Client::System With properly initialized client InstanceMethods #restart Should be able to wait after a safe restart
rspec ./spec/func_tests/system_spec.rb:44 # JenkinsApi::Client::System With properly initialized client InstanceMethods #restart Should be able to force restart a Jenkins server
rspec ./spec/func_tests/system_spec.rb:48 # JenkinsApi::Client::System With properly initialized client InstanceMethods #restart Should be able to wait after a force restart
rspec ./spec/func_tests/system_spec.rb:54 # JenkinsApi::Client::System With properly initialized client InstanceMethods #reload Should be able to reload a Jenkins server
rspec ./spec/func_tests/system_spec.rb:57 # JenkinsApi::Client::System With properly initialized client InstanceMethods #reload Should be able to wait after a force restart
rspec ./spec/func_tests/view_spec.rb:30 # JenkinsApi::Client::View With properly initialized client InstanceMethods #list Should be able to list all views
rspec ./spec/func_tests/view_spec.rb:36 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create accepts the name of the view and creates the view
rspec ./spec/func_tests/view_spec.rb:42 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create accepts spaces and other characters in the view name
rspec ./spec/func_tests/view_spec.rb:48 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create accepts the name of view and creates a listview
rspec ./spec/func_tests/view_spec.rb:54 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create accepts the name of view and creates a myview
rspec ./spec/func_tests/view_spec.rb:60 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create raises an error when unsupported view type is specified
rspec ./spec/func_tests/view_spec.rb:77 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create_list_view accepts just the name of the view and creates the view
rspec ./spec/func_tests/view_spec.rb:84 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create_list_view accepts description as an option
rspec ./spec/func_tests/view_spec.rb:92 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create_list_view accepts filter_queue as an option
rspec ./spec/func_tests/view_spec.rb:100 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create_list_view accepts filter_executors as an option
rspec ./spec/func_tests/view_spec.rb:108 # JenkinsApi::Client::View With properly initialized client InstanceMethods #create_list_view accepts regex as an option
rspec ./spec/func_tests/view_spec.rb:122 # JenkinsApi::Client::View With properly initialized client InstanceMethods #delete accepts the name of the view and deletes from Jenkins
rspec ./spec/func_tests/view_spec.rb:130 # JenkinsApi::Client::View With properly initialized client InstanceMethods #list_jobs accepts the view name and lists all jobs in the view
rspec ./spec/func_tests/view_spec.rb:136 # JenkinsApi::Client::View With properly initialized client InstanceMethods #exists? accepts the vie name and returns true if the view exists
rspec ./spec/func_tests/view_spec.rb:147 # JenkinsApi::Client::View With properly initialized client InstanceMethods #add_job accepts the job and and adds it to the specified view
rspec ./spec/func_tests/view_spec.rb:173 # JenkinsApi::Client::View With properly initialized client InstanceMethods #remove_job accepts the job name and removes it from the specified view
rspec ./spec/func_tests/view_spec.rb:182 # JenkinsApi::Client::View With properly initialized client InstanceMethods #get_config obtaines the view config.xml from the server
rspec ./spec/func_tests/view_spec.rb:190 # JenkinsApi::Client::View With properly initialized client InstanceMethods #post_config posts the given config.xml to the jenkins server's view

Jenkins XSS disable option should be supported by jenkins_api_client

Jenkins supports a security option where you can disable XSS attacks. This involves obtaining crumb from the crumbIssues of Jenkins whenever we do a POST. This can be passed in as an option may be :use_crumb = true which will get the crumb before doing POST. The default will be false.

Remove the warning

/usr/lib/ruby/gems/1.8/gems/jenkins_api_client-0.8.0/lib/jenkins_api_client/cli/../client.rb:34: warning: already initialized constant DEFAULT_SERVER_PORT
/usr/lib/ruby/gems/1.8/gems/jenkins_api_client-0.8.0/lib/jenkins_api_client/cli/../client.rb:35: warning: already initialized constant VALID_PARAMS

stop_build is checking string as a TrueClass

The stop_build in Job compares string is_building as TrueClass. It will work whether it is "true", "false" or "whatever". Check for specific string values.

def stop_build(job_name, build_number = 0)
  build_number = get_current_build_number(job_name) if build_number == 0
  raise "No builds for #{job_name}" unless build_number
  # Check and see if the build is running
  is_building = @client.api_get_request(
    "/job/#{job_name}/#{build_number}"
  )["building"]
  if is_building
    @client.api_post_request("/job/#{job_name}/#{build_number}/stop")
  end
end

Improve error messages for Views

Jenkins sends a huge html page if something goes wrong in creating view as we use configSubmit. So catching the exception and displaying it in a more readable manner will improve usability.

Introduce Ability to Mock a Jenkins Server to perform unit tests

It would be nice to have two different classes for each components, one for Real class and the other for Mock class. The Real class will communicate with a real Jenkins server where as the Mock class will imitate the response of a Jenkins server. This Mocking should be done for all functionality that should be tested.

An example of this mocking architecture can be found in the Fog gem here: https://github.com/fog/fog

VALID_PARAMS is never used in Client and it accepts any value given

The valid params here VALID_PARAMS = %w(server_ip server_port jenkins_path username password debug) is intentionally created to check if the given values are valid and set only those values as instance variables. But this is never used. It should check before setting them as instance variables.

args.each do |key, value|
  instance_variable_set("@#{key}", value) if value && VALID_PARAMS.include? key
end if args.is_a? Hash

Implement BuildQueue class

Jenkins offers a BuildQueue API which gives information about jobs that in the build queue such as the number of jobs, their names, how long they are in the queue, what are the causes, the reason why they are in the queue, etc. Implement a class with basic features.

Https

Https is supported it seems. From documentation. But when I try :ssl => true it just returns
SSL_connect returned=1 errno=0 state=unknown state: unknown protocol (OpenSSL::SSL::SSLError)

Default is false. Is there some documenation on how this argument is to be used?

Spaces in job, view, node etc are not currently supported.

Current jenkins_api_client implementation doesn't support spaces in job, view, node names.
Recently @kevinhcross submitted a pull request #29 that fixes this problem with the Job interface. Jenkins supports spaces for views and nodes as well. Moving the logic of encoding the names to the client class will make it generic.

Example:

def api_post_request(url_prefix, form_data = nil)
  url_prefix = "#{@jenkins_path}#{url_prefix}"
  http = Net::HTTP.start(@server_ip, @server_port)
  to_post = "#{url_prefix}"
  request = Net::HTTP::Post.new(URI.encode(to_post))
  puts "[INFO] PUT #{to_post}" if @debug
  request.basic_auth @username, @password
  request.content_type = 'application/json'
  request.set_form_data(form_data) unless form_data.nil?
  response = http.request(request)
  msg = "HTTP Code: #{response.code}, Response Body: #{response.body}"
  case response.code.to_i
  when 200, 302
    return response.code
  when 404
    raise Exceptions::NotFoundException.new(msg)
  when 500
    raise Exceptions::InternelServerErrorException.new(msg)
  else
    raise Exceptions::ApiException.new(msg)
  end
end

This should be changed in all api methods in client.rb. Also adding a test with space in job, node, and view names would be great.

Create functions to handle the 'Next Execution' dialoge

As a user of the jenkins_api_client, I want to be able to query the status of the Next Execution panel (lower left, below running jobs). The jobs in this panel are scheduled jobs in jenkins to be executed in the future via the cron type scheduling.

Create a method for recreating a job

As a hack, create a method called 'recreate' on the Job class so we can clear the build details of that particular job.

Steps to this method should be simple.

  1. Obtain the job's xml.
  2. Delete the job.
  3. Create the job with the same name and with the xml obtained in Step 1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.