sensu-plugins/sensu-plugins-jenkins

View on GitHub
bin/check-jenkins-job-status.rb

Summary

Maintainability
A
35 mins
Test Coverage
#! /usr/bin/env ruby
#
#   check-jenkins-job-status
#
# DESCRIPTION:
#   Query jenkins API asking for job status
#
# OUTPUT:
#   plain text
#
# PLATFORMS:
#   Linux
#
# DEPENDENCIES:
#   gem: sensu-plugin
#   jenkins_api_client
#
# USAGE:
#   #YELLOW
#
# NOTES:
#   #YELLOW
#   add url to job's log for CRITICAL state
#
# LICENSE:
#   Copyright 2014 SUSE, GmbH <happy-customer@suse.de>
#   Released under the same terms as Sensu (the MIT license); see LICENSE
#   for details.
#

require 'sensu-plugin/check/cli'
require 'jenkins_api_client'

#
# Jenkins Job Check
#
class JenkinsJobChecker < Sensu::Plugin::Check::CLI
  option :server_api_url,
         description: 'hostname running Jenkins API',
         short: '-u JENKINS-API-HOST',
         long: '--url JENKINS-API-HOST',
         required: true

  option :job_list,
         description: 'Name of a job/pattern to query. Wrap with quotes. E.g. \'^GCC\'',
         short: '-j JOB-LIST',
         long: '--jobs JOB-LIST',
         required: true

  option :client_log_level,
         description: 'log level option 0..3 to client',
         short: '-v CLIENT-LOG-LEVEL',
         long: '--verbose CLIENT-LOG-LEVEL',
         default: 3

  option :username,
         description: 'Username for Jenkins instance',
         short: '-U USERNAME',
         long: '--username USERNAME',
         required: false

  option :password,
         description: "Password for Jenkins instance. Either set ENV['JENKINS_PASS'] or provide it as an option",
         short: '-p PASSWORD',
         long: '--password PASSWORD',
         required: false,
         default: ENV['JENKINS_PASS']

  option :include_warnings,
         description: 'whether to report unstable jobs as a warning',
         short: '-w',
         long: '--include-warnings',
         boolean: true,
         required: false,
         default: false

  def run
    if failed_jobs.any?
      critical "Jobs reporting failure: #{failed_job_names}, jobs reported as unstable: #{unstable_job_names}"
    elsif unstable_jobs.any? && config[:include_warnings]
      warning "Jobs reported as unstable: #{unstable_job_names}"
    else
      ok 'All queried jobs report success'
    end
  end

  private

  def jenkins_api_client
    @jenkins_api_client ||= JenkinsApi::Client.new(
      server_url: config[:server_api_url],
      log_level: config[:client_log_level].to_i,
      username: config[:username], password: config[:password]
    )
  end

  def jobs_statuses
    @job_listing ||=
      if config[:job_list] =~ /\^/
        jenkins_api_client.job.list(config[:job_list]).reduce({}) do |listing, job_name| # rubocop:disable Style/EachWithObject
          listing[job_name] = job_status(job_name)
          listing
        end
      else
        { config[:job_list] => job_status(config[:job_list]) }
      end
  end

  def job_status(job_name)
    status = jenkins_api_client.job.get_current_build_status(job_name)
    # If the job is currently running, get the status of the last build instead
    if status == 'running'
      build = jenkins_api_client.job.get_build_details(job_name, 'lastCompletedBuild')
      if build && build['result']
        status = build['result'].downcase
      end
    end
    status
  rescue
    critical "Error looking up Jenkins job: #{job_name}"
  end

  def unstable_jobs
    jobs_statuses.select { |_job_name, status| status == 'unstable' }
  end

  def failed_jobs
    jobs_statuses.select { |_job_name, status| status == 'failure' }
  end

  def unstable_job_names
    unstable_jobs.keys.join(', ')
  end

  def failed_job_names
    failed_jobs.keys.join(', ')
  end
end