Class: JenkinsApi::Client
- Inherits:
-
Object
- Object
- JenkinsApi::Client
- Defined in:
- lib/improved_jenkins_client/client.rb,
lib/improved_jenkins_client.rb,
lib/improved_jenkins_client/job.rb,
lib/improved_jenkins_client/node.rb,
lib/improved_jenkins_client/root.rb,
lib/improved_jenkins_client/user.rb,
lib/improved_jenkins_client/view.rb,
lib/improved_jenkins_client/system.rb,
lib/improved_jenkins_client/version.rb,
lib/improved_jenkins_client/build_queue.rb,
lib/improved_jenkins_client/plugin_manager.rb,
lib/improved_jenkins_client/plugin_settings/base.rb,
lib/improved_jenkins_client/plugin_settings/hipchat.rb,
lib/improved_jenkins_client/plugin_settings/collection.rb,
lib/improved_jenkins_client/plugin_settings/workspace_cleanup.rb
Overview
This is the client class that acts as the bridge between the subclasses and Jenkins. This class contains methods that performs GET and POST requests for various operations.
Defined Under Namespace
Modules: PluginSettings Classes: BuildQueue, Job, Node, PluginManager, Root, System, User, View
Constant Summary collapse
- DEFAULT_SERVER_PORT =
Default port to be used to connect to Jenkins
8080
- DEFAULT_TIMEOUT =
Default timeout in seconds to be used while performing operations
120
- DEFAULT_HTTP_OPEN_TIMEOUT =
10
- DEFAULT_HTTP_READ_TIMEOUT =
120
- VALID_PARAMS =
Parameters that are permitted as options while initializing the client
[ "server_url", "server_ip", "server_port", "proxy_ip", "proxy_port", "proxy_protocol", "jenkins_path", "username", "password", "password_base64", "logger", "log_location", "log_level", "timeout", "http_open_timeout", "http_read_timeout", "ssl", "pkcs_file_path", "pass_phrase", "ca_file", "follow_redirects", "identity_file", "cookies", "pretty_json_responses" ].freeze
- MAJOR =
Major version of the gem
1
- MINOR =
Minor version of the gem
6
- TINY =
Tiny version of the gem used for patches
7
- PRE =
Used for pre-releases
nil
- VERSION =
Version String of Jenkins API Client.
[MAJOR, MINOR, TINY, PRE].compact.join('.')
Instance Attribute Summary collapse
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#timeout ⇒ Object
Returns the value of attribute timeout.
Instance Method Summary collapse
-
#api_get_request(url_prefix, tree = nil, url_suffix = "/api/json", raw_response = false) ⇒ String, Hash
Sends a GET request to the Jenkins CI server with the specified URL.
-
#api_post_request(url_prefix, form_data = {}, raw_response = false) ⇒ String
Sends a POST message to the Jenkins CI server with the specified URL.
-
#compare_versions(version_a, version_b) ⇒ Object
Compare two version strings (A and B) if A == B, returns 0 if A > B, returns 1 if A < B, returns -1.
-
#deconstruct_version_string(version) ⇒ Object
Converts a version string to a list of integers This makes it easier to compare versions since in ‘version-speak’, v 1.2 is a lot older than v 1.102 - and simple < > on version strings doesn’t work so well.
-
#exec_cli(command, args = []) ⇒ String
Execute the Jenkins CLI.
-
#exec_script(script_text) ⇒ String
Executes the provided groovy script on the Jenkins CI server.
-
#get_artifact(job_name, filename) ⇒ Object
Connects to the server and downloads artifacts to a specified location.
-
#get_artifacts(job_name, dldir, build_number = nil) ⇒ Object
Connects to the server and download all artifacts of a build to a specified location.
-
#get_config(url_prefix) ⇒ String
Obtains the configuration of a component from the Jenkins CI server.
-
#get_hudson_version ⇒ String
Obtain the Hudson version of the CI server Only queries Hudson/Jenkins if the version is not already stored.
-
#get_jenkins_version ⇒ String
Obtains the jenkins version from the API Only queries Jenkins if the version is not already stored.
-
#get_root ⇒ Net::HTTP::Response
Obtains the root of Jenkins server.
-
#get_server_date ⇒ String
Obtain the date of the Jenkins server.
- #init_update_center ⇒ Object
-
#initialize(args) ⇒ JenkinsApi::Client
constructor
Initialize a Client object with Jenkins CI server credentials.
-
#inspect ⇒ Object
Overrides the inspect method to get rid of the credentials being shown in the in interactive IRB sessions and also when the ‘inspect` method is called.
-
#job ⇒ JenkinsApi::Client::Job
Creates an instance to the Job class by passing a reference to self.
-
#node ⇒ JenkinsApi::Client::Node
Creates an instance to the Node class by passing a reference to self.
-
#plugin ⇒ JenkinsApi::Client::PluginManager
Creates an instance to the PluginManager by passing a reference to self.
-
#post_config(url_prefix, xml) ⇒ String
Posts the given xml configuration to the url given.
- #post_data(url_prefix, data, content_type) ⇒ Object
- #post_json(url_prefix, json) ⇒ Object
-
#queue ⇒ JenkinsApi::Client::BuildQueue
Creates an instance to the BuildQueue by passing a reference to self.
-
#root ⇒ JenkinsApi::Client::Root
Creates an instance of the Root class by passing a reference to self.
-
#system ⇒ JenkinsApi::Client::System
Creates an instance to the System class by passing a reference to self.
-
#to_s ⇒ String
Returns a string representing the class name.
-
#use_crumbs? ⇒ Boolean
Checks if Jenkins uses crumbs (i.e) the XSS disable option is checked in Jenkins’ security settings.
-
#use_security? ⇒ Boolean
Checks if Jenkins uses security.
-
#user ⇒ JenkinsApi::Client::User
Creates an instance of the User class by passing a reference to self.
-
#view ⇒ JenkinsApi::Client::View
Creates an instance to the View class by passing a reference to self.
Constructor Details
#initialize(args) ⇒ JenkinsApi::Client
Initialize a Client object with Jenkins CI server credentials
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/improved_jenkins_client/client.rb', line 116 def initialize(args) args = symbolize_keys(args) args.each do |key, value| if value && VALID_PARAMS.include?(key.to_s) instance_variable_set("@#{key}", value) end end if args.is_a? Hash # Server IP or Server URL must be specific unless @server_ip || @server_url raise ArgumentError, "Server IP or Server URL is required to connect" + " to Jenkins" end # Get info from the server_url, if we got one if @server_url server_uri = URI.parse(@server_url) @server_ip = server_uri.host @server_port = server_uri.port @ssl = server_uri.scheme == "https" @jenkins_path = server_uri.path # read username and password from the URL # only set if @username and @password are not already set via explicit options @username ||= server_uri.user @password ||= server_uri.password end # Username/password are optional as some jenkins servers do not require # authentication if @username && !(@password || @password_base64) raise ArgumentError, "If username is provided, password is required" end if @proxy_ip.nil? ^ @proxy_port.nil? raise ArgumentError, "Proxy IP and port must both be specified or" + " both left nil" end @jenkins_path ||= "" @jenkins_path.gsub!(/\/$/,"") # remove trailing slash if there is one @server_port = DEFAULT_SERVER_PORT unless @server_port @timeout = DEFAULT_TIMEOUT unless @timeout @http_open_timeout = DEFAULT_HTTP_OPEN_TIMEOUT unless @http_open_timeout @http_read_timeout = DEFAULT_HTTP_READ_TIMEOUT unless @http_read_timeout @ssl ||= false @proxy_protocol ||= 'http' # Setting log options if @logger raise ArgumentError, "logger parameter must be a Logger object" unless @logger.is_a?(Logger) raise ArgumentError, "log_level should not be set if using custom logger" if @log_level raise ArgumentError, "log_location should not be set if using custom logger" if @log_location else @log_location = STDOUT unless @log_location @log_level = Logger::INFO unless @log_level @logger = Logger.new(@log_location) @logger.level = @log_level end # Base64 decode inserts a newline character at the end. As a workaround # added chomp to remove newline characters. I hope nobody uses newline # characters at the end of their passwords :) @password = Base64.decode64(@password_base64).chomp if @password_base64 # No connections are made to the Jenkins server during initialize to # allow the unit tests to behave normally as mocking is simpler this way. # If this variable is nil, the first POST request will query the API and # populate this variable. @crumbs_enabled = nil # The crumbs hash. Store it so that we don't have to obtain the crumb for # every POST request. It appears that the crumb doesn't change often. @crumb = {} # This is the number of times to refetch the crumb if it ever expires. @crumb_max_retries = 3 end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
44 45 46 |
# File 'lib/improved_jenkins_client/client.rb', line 44 def logger @logger end |
#timeout ⇒ Object
Returns the value of attribute timeout.
44 45 46 |
# File 'lib/improved_jenkins_client/client.rb', line 44 def timeout @timeout end |
Instance Method Details
#api_get_request(url_prefix, tree = nil, url_suffix = "/api/json", raw_response = false) ⇒ String, Hash
Sends a GET request to the Jenkins CI server with the specified URL
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
# File 'lib/improved_jenkins_client/client.rb', line 416 def api_get_request(url_prefix, tree = nil, url_suffix ="/api/json", raw_response = false) url_prefix = "#{@jenkins_path}#{url_prefix}" to_get = "" if tree to_get = "#{url_prefix}#{url_suffix}?#{tree}" query_param_separator = "&" else to_get = "#{url_prefix}#{url_suffix}" query_param_separator = "?" end if @pretty_json_responses && url_suffix == "/api/json" to_get += query_param_separator to_get += "pretty=true" end request = Net::HTTP::Get.new(to_get) @logger.debug "GET #{to_get}" response = make_http_request(request) if raw_response handle_exception(response, "raw", full_url: to_get) else handle_exception(response, "body", url_suffix =~ /json/, full_url: to_get) end end |
#api_post_request(url_prefix, form_data = {}, raw_response = false) ⇒ String
Sends a POST message to the Jenkins CI server with the specified URL
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 |
# File 'lib/improved_jenkins_client/client.rb', line 452 def api_post_request(url_prefix, form_data = {}, raw_response = false) retries = @crumb_max_retries begin refresh_crumbs # Added form_data default {} instead of nil to help with proxies # that barf with empty post request = Net::HTTP::Post.new("#{@jenkins_path}#{url_prefix}") @logger.debug "POST #{url_prefix}" if @crumbs_enabled request[@crumb["crumbRequestField"]] = @crumb["crumb"] end request.set_form_data(form_data) response = make_http_request(request) if raw_response handle_exception(response, "raw") else handle_exception(response) end rescue Exceptions::ForbiddenException => e refresh_crumbs(true) if @crumbs_enabled @logger.info "Retrying: #{@crumb_max_retries - retries + 1} out of" + " #{@crumb_max_retries} times..." retries -= 1 if retries > 0 retry else raise Exceptions::ForbiddenWithCrumb.new(@logger, e.) end else raise end end end |
#compare_versions(version_a, version_b) ⇒ Object
Compare two version strings (A and B) if A == B, returns 0 if A > B, returns 1 if A < B, returns -1
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 |
# File 'lib/improved_jenkins_client/client.rb', line 632 def compare_versions(version_a, version_b) if version_a == version_b return 0 else version_a_d = deconstruct_version_string(version_a) version_b_d = deconstruct_version_string(version_b) if version_a_d[0] > version_b_d[0] || (version_a_d[0] == version_b_d[0] && version_a_d[1] > version_b_d[1]) || (version_a_d[0] == version_b_d[0] && version_a_d[1] == version_b_d[1] && version_a_d[2] > version_b_d[2]) return 1 else return -1 end end end |
#deconstruct_version_string(version) ⇒ Object
Converts a version string to a list of integers This makes it easier to compare versions since in ‘version-speak’, v 1.2 is a lot older than v 1.102 - and simple < > on version strings doesn’t work so well
616 617 618 619 620 621 622 623 624 625 626 |
# File 'lib/improved_jenkins_client/client.rb', line 616 def deconstruct_version_string(version) match = version.match(/^(\d+)\.(\d+)(?:\.(\d+))?$/) # Match should have 4 parts [0] = input string, [1] = major # [2] = minor, [3] = patch (possibly blank) if match && match.size == 4 return [match[1].to_i, match[2].to_i, match[3].to_i || 0] else return nil end end |
#exec_cli(command, args = []) ⇒ String
Execute the Jenkins CLI
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 |
# File 'lib/improved_jenkins_client/client.rb', line 679 def exec_cli(command, args = []) base_dir = File.dirname(__FILE__) server_url = "http://#{@server_ip}:#{@server_port}/#{@jenkins_path}" cmd = "java -jar #{base_dir}/../../java_deps/jenkins-cli.jar -s #{server_url}" cmd << " -i #{@identity_file}" if @identity_file && !@identity_file.empty? cmd << " #{command}" cmd << " --username #{@username} --password #{@password}" if @identity_file.nil? || @identity_file.empty? cmd << ' ' cmd << args.join(' ') java_cmd = Mixlib::ShellOut.new(cmd) # Run the command java_cmd.run_command if java_cmd.stderr.empty? java_cmd.stdout.chomp else # The stderr has a stack trace of the Java program. We'll already have # a stack trace for Ruby. So just display a descriptive message for the # error thrown by the CLI. raise Exceptions::CLIException.new( @logger, java_cmd.stderr.split("\n").first ) end end |
#exec_script(script_text) ⇒ String
Executes the provided groovy script on the Jenkins CI server
664 665 666 667 |
# File 'lib/improved_jenkins_client/client.rb', line 664 def exec_script(script_text) response = api_post_request('/scriptText', {'script' => script_text}, true) response.body end |
#get_artifact(job_name, filename) ⇒ Object
Connects to the server and downloads artifacts to a specified location
288 289 290 291 292 293 294 295 296 |
# File 'lib/improved_jenkins_client/client.rb', line 288 def get_artifact(job_name,filename) @artifact = job.find_artifact(job_name) response = make_http_request(Net::HTTP::Get.new(@artifact)) if response.code == "200" File.write(File.(filename), response.body) else raise "Couldn't get the artifact" end end |
#get_artifacts(job_name, dldir, build_number = nil) ⇒ Object
Connects to the server and download all artifacts of a build to a specified location
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/improved_jenkins_client/client.rb', line 305 def get_artifacts(job_name, dldir, build_number = nil) @artifacts = job.find_artifacts(job_name,build_number) results = [] @artifacts.each do |artifact| uri = URI.parse(artifact) http = Net::HTTP.new(uri.host, uri.port) http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.use_ssl = @ssl request = Net::HTTP::Get.new(uri.request_uri) request.basic_auth(@username, @password) response = http.request(request) # we want every thing after the last 'build' in the path to become the filename if artifact.include?('/build/') filename = artifact.split("/build/").last.gsub('/','-') else filename = File.basename(artifact) end filename = File.join(dldir, filename) results << filename if response.code == "200" File.write(File.(filename), response.body) else raise "Couldn't get the artifact #{artifact} for job #{job}" end end results end |
#get_config(url_prefix) ⇒ String
Obtains the configuration of a component from the Jenkins CI server
496 497 498 499 500 501 |
# File 'lib/improved_jenkins_client/client.rb', line 496 def get_config(url_prefix) request = Net::HTTP::Get.new("#{@jenkins_path}#{url_prefix}/config.xml") @logger.debug "GET #{url_prefix}/config.xml" response = make_http_request(request) handle_exception(response, "body") end |
#get_hudson_version ⇒ String
Obtain the Hudson version of the CI server Only queries Hudson/Jenkins if the version is not already stored. Note that the version is auto-updated after every request made to Jenkins since it is returned as a header in every response
607 608 609 610 |
# File 'lib/improved_jenkins_client/client.rb', line 607 def get_hudson_version get_root if @hudson_version.nil? @hudson_version end |
#get_jenkins_version ⇒ String
Obtains the jenkins version from the API Only queries Jenkins if the version is not already stored. Note that the version is auto-updated after every request made to Jenkins since it is returned as a header in every response
595 596 597 598 |
# File 'lib/improved_jenkins_client/client.rb', line 595 def get_jenkins_version get_root if @jenkins_version.nil? @jenkins_version end |
#get_root ⇒ Net::HTTP::Response
Obtains the root of Jenkins server. This function is used to see if Jenkins is running
400 401 402 403 404 |
# File 'lib/improved_jenkins_client/client.rb', line 400 def get_root @logger.debug "GET #{@jenkins_path}/" request = Net::HTTP::Get.new("#{@jenkins_path}/") make_http_request(request) end |
#get_server_date ⇒ String
Obtain the date of the Jenkins server
653 654 655 656 |
# File 'lib/improved_jenkins_client/client.rb', line 653 def get_server_date response = get_root response["Date"] end |
#init_update_center ⇒ Object
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 |
# File 'lib/improved_jenkins_client/client.rb', line 551 def init_update_center @logger.info "Initializing Jenkins Update Center..." @logger.debug "Obtaining the JSON data for Update Center..." # TODO: Clean me up update_center_data = open("https://updates.jenkins.io/current/update-center.json").read # The Jenkins mirror returns the data in the following format # updateCenter.post( # {.. JSON data...} # ); # which is used by the Javascript used by the Jenkins UI to send to Jenkins. # update_center_data.gsub!("updateCenter.post(\n", "") update_center_data.gsub!("\n);", "") @logger.debug "Posting the obtained JSON to Jenkins Update Center..." post_json("/updateCenter/byId/default/postBack", update_center_data) end |
#inspect ⇒ Object
Overrides the inspect method to get rid of the credentials being shown in the in interactive IRB sessions and also when the ‘inspect` method is called. Just print the important variables.
269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/improved_jenkins_client/client.rb', line 269 def inspect "#<JenkinsApi::Client:0x#{(self.__id__ * 2).to_s(16)}" + " @ssl=#{@ssl.inspect}," + " @ca_file=#{@ca_file.inspect}," + " @log_location=#{@log_location.inspect}," + " @log_level=#{@log_level.inspect}," + " @crumbs_enabled=#{@crumbs_enabled.inspect}," + " @follow_redirects=#{@follow_redirects.inspect}," + " @jenkins_path=#{@jenkins_path.inspect}," + " @timeout=#{@timeout.inspect}>," + " @http_open_timeout=#{@http_open_timeout.inspect}>," + " @http_read_timeout=#{@http_read_timeout.inspect}>" end |
#job ⇒ JenkinsApi::Client::Job
Creates an instance to the Job class by passing a reference to self
196 197 198 |
# File 'lib/improved_jenkins_client/client.rb', line 196 def job JenkinsApi::Client::Job.new(self) end |
#node ⇒ JenkinsApi::Client::Node
Creates an instance to the Node class by passing a reference to self
212 213 214 |
# File 'lib/improved_jenkins_client/client.rb', line 212 def node JenkinsApi::Client::Node.new(self) end |
#plugin ⇒ JenkinsApi::Client::PluginManager
Creates an instance to the PluginManager by passing a reference to self
237 238 239 |
# File 'lib/improved_jenkins_client/client.rb', line 237 def plugin JenkinsApi::Client::PluginManager.new(self) end |
#post_config(url_prefix, xml) ⇒ String
Posts the given xml configuration to the url given
510 511 512 |
# File 'lib/improved_jenkins_client/client.rb', line 510 def post_config(url_prefix, xml) post_data(url_prefix, xml, 'application/xml;charset=UTF-8') end |
#post_data(url_prefix, data, content_type) ⇒ Object
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
# File 'lib/improved_jenkins_client/client.rb', line 518 def post_data(url_prefix, data, content_type) retries = @crumb_max_retries begin refresh_crumbs request = Net::HTTP::Post.new("#{@jenkins_path}#{url_prefix}") @logger.debug "POST #{url_prefix}" request.body = data request.content_type = content_type if @crumbs_enabled request[@crumb["crumbRequestField"]] = @crumb["crumb"] end response = make_http_request(request) handle_exception(response) rescue Exceptions::ForbiddenException => e refresh_crumbs(true) if @crumbs_enabled @logger.info "Retrying: #{@crumb_max_retries - retries + 1} out of" + " #{@crumb_max_retries} times..." retries -= 1 if retries > 0 retry else raise Exceptions::ForbiddenWithCrumb.new(@logger, e.) end else raise end end end |
#post_json(url_prefix, json) ⇒ Object
514 515 516 |
# File 'lib/improved_jenkins_client/client.rb', line 514 def post_json(url_prefix, json) post_data(url_prefix, json, 'application/json;charset=UTF-8') end |
#queue ⇒ JenkinsApi::Client::BuildQueue
Creates an instance to the BuildQueue by passing a reference to self
228 229 230 |
# File 'lib/improved_jenkins_client/client.rb', line 228 def queue JenkinsApi::Client::BuildQueue.new(self) end |
#root ⇒ JenkinsApi::Client::Root
Creates an instance of the Root class by passing a reference to self
253 254 255 |
# File 'lib/improved_jenkins_client/client.rb', line 253 def root JenkinsApi::Client::Root.new(self) end |
#system ⇒ JenkinsApi::Client::System
Creates an instance to the System class by passing a reference to self
204 205 206 |
# File 'lib/improved_jenkins_client/client.rb', line 204 def system JenkinsApi::Client::System.new(self) end |
#to_s ⇒ String
Returns a string representing the class name
261 262 263 |
# File 'lib/improved_jenkins_client/client.rb', line 261 def to_s "#<JenkinsApi::Client>" end |
#use_crumbs? ⇒ Boolean
Checks if Jenkins uses crumbs (i.e) the XSS disable option is checked in Jenkins’ security settings
574 575 576 577 |
# File 'lib/improved_jenkins_client/client.rb', line 574 def use_crumbs? response = api_get_request("", "tree=useCrumbs") response["useCrumbs"] end |
#use_security? ⇒ Boolean
Checks if Jenkins uses security
583 584 585 586 |
# File 'lib/improved_jenkins_client/client.rb', line 583 def use_security? response = api_get_request("", "tree=useSecurity") response["useSecurity"] end |
#user ⇒ JenkinsApi::Client::User
Creates an instance of the User class by passing a reference to self
245 246 247 |
# File 'lib/improved_jenkins_client/client.rb', line 245 def user JenkinsApi::Client::User.new(self) end |
#view ⇒ JenkinsApi::Client::View
Creates an instance to the View class by passing a reference to self
220 221 222 |
# File 'lib/improved_jenkins_client/client.rb', line 220 def view JenkinsApi::Client::View.new(self) end |