jenkins_api_client 1.5.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a4d136e1d892db0bf4411fbaa520ff62efc5162c
4
- data.tar.gz: 12dd02a2aefaf038614bb1c2ca74990890730a33
2
+ SHA256:
3
+ metadata.gz: a499520438bb2fdcedc254768700d30b74c5c083e2557048a97b8a9f9b2e23ea
4
+ data.tar.gz: cf1d9d37530711baed6c6909ee34077a07c0161c68705ca3c7691d1ac53ba82e
5
5
  SHA512:
6
- metadata.gz: 639225407882ad7ad86443327ee0de6e9d54df384e068d22dbfeea478e58e96cbc85f18cb5e5138e66beb2b121433a3f71335e641c8b65c8b13c09e2b613b36f
7
- data.tar.gz: a5e5b5d15e33dfe19f8b797524d250b2e78422ea41b7e57ee36d32ee7fed273ee32f5c77e0c01fc9b9c6122db7b0b3a48b0423662652024ec282b4dc8091276e
6
+ metadata.gz: '05659348d3846adbba1bb231ef5e751515d26aff76a2ea16d42ed4973507ca606192bfcd0bc5915d14e636c110d21dd3e2f99e59578f43e110c3f84724a3834f'
7
+ data.tar.gz: 0ad06756109a85dda032414524752cba25575061afb4f4b030d63d34d62b0d16373048bed46b0b624c4be1b204c858f5ca5b75592302328ea16c5765b4a065e2
@@ -6,18 +6,15 @@ Gem::Specification.new do |s|
6
6
  s.name = "jenkins_api_client"
7
7
  s.version = ::JenkinsApi::Client::VERSION
8
8
 
9
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
- s.require_paths = ["lib"]
11
9
  s.authors = ["Kannan Manickam"]
12
10
  s.description = "\nThis is a simple and easy-to-use Jenkins Api client with features focused on\nautomating Job configuration programaticaly and so forth"
13
11
  s.email = ["arangamani.kannan@gmail.com"]
14
12
  s.executables = ['jenkinscli']
15
13
  s.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r{lib/|bin/|java_deps/|gemspec}) }
16
- s.require_paths = ['lib']
17
14
  s.homepage = 'https://github.com/arangamani/jenkins_api_client'
18
- s.required_ruby_version = ::Gem::Requirement.new('~> 2.1')
19
- s.rubygems_version = "2.4.5.1"
15
+ s.required_ruby_version = '>= 2.7'
20
16
  s.summary = "Jenkins JSON API Client"
17
+ s.licenses = ["MIT"]
21
18
 
22
19
  s.add_dependency 'nokogiri', '~> 1.6'
23
20
  s.add_dependency 'thor', '>= 0.16.0'
@@ -25,5 +22,5 @@ Gem::Specification.new do |s|
25
22
  s.add_dependency 'mixlib-shellout', '>= 1.1.0'
26
23
  s.add_dependency 'socksify', '>= 1.7.0'
27
24
  s.add_dependency 'json', '>= 1.0'
25
+ s.add_dependency 'addressable', '~> 2.7'
28
26
  end
29
-
@@ -30,6 +30,7 @@ require 'mixlib/shellout'
30
30
  require 'uri'
31
31
  require 'logger'
32
32
  require 'socksify/http'
33
+ require 'open-uri'
33
34
 
34
35
  # The main module that contains the Client class and all subclasses that
35
36
  # communicate with the Jenkins's Remote Access API.
@@ -66,6 +67,9 @@ module JenkinsApi
66
67
  "http_open_timeout",
67
68
  "http_read_timeout",
68
69
  "ssl",
70
+ "pkcs_file_path",
71
+ "pass_phrase",
72
+ "ca_file",
69
73
  "follow_redirects",
70
74
  "identity_file",
71
75
  "cookies"
@@ -91,6 +95,9 @@ module JenkinsApi
91
95
  # @option args [String] :proxy_protocol the proxy protocol ('socks' or 'http' (defaults to HTTP)
92
96
  # @option args [String] :jenkins_path ("/") the optional context path for Jenkins
93
97
  # @option args [Boolean] :ssl (false) indicates if Jenkins is accessible over HTTPS
98
+ # @option args [String] :pkcs_file_path ("/") the optional context path for pfx or p12 binary certificate file
99
+ # @option args [String] :pass_phrase password for pkcs_file_path certificate file
100
+ # @option args [String] :ca_file the path to a PEM encoded file containing trusted certificates used to verify peer certificate
94
101
  # @option args [Boolean] :follow_redirects this argument causes the client to follow a redirect (jenkins can
95
102
  # return a 30x when starting a build)
96
103
  # @option args [Fixnum] :timeout (120) This argument sets the timeout for operations that take longer (in seconds)
@@ -237,6 +244,14 @@ module JenkinsApi
237
244
  JenkinsApi::Client::User.new(self)
238
245
  end
239
246
 
247
+ # Creates an instance of the Root class by passing a reference to self
248
+ #
249
+ # @return [JenkinsApi::Client::Root] An object of Root subclass
250
+ #
251
+ def root
252
+ JenkinsApi::Client::Root.new(self)
253
+ end
254
+
240
255
  # Returns a string representing the class name
241
256
  #
242
257
  # @return [String] string representation of class name
@@ -252,6 +267,7 @@ module JenkinsApi
252
267
  def inspect
253
268
  "#<JenkinsApi::Client:0x#{(self.__id__ * 2).to_s(16)}" +
254
269
  " @ssl=#{@ssl.inspect}," +
270
+ " @ca_file=#{@ca_file.inspect}," +
255
271
  " @log_location=#{@log_location.inspect}," +
256
272
  " @log_level=#{@log_level.inspect}," +
257
273
  " @crumbs_enabled=#{@crumbs_enabled.inspect}," +
@@ -269,13 +285,7 @@ module JenkinsApi
269
285
  #
270
286
  def get_artifact(job_name,filename)
271
287
  @artifact = job.find_artifact(job_name)
272
- uri = URI.parse(@artifact)
273
- http = Net::HTTP.new(uri.host, uri.port)
274
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
275
- http.use_ssl = @ssl
276
- request = Net::HTTP::Get.new(uri.request_uri)
277
- request.basic_auth(@username, @password)
278
- response = http.request(request)
288
+ response = make_http_request(Net::HTTP::Get.new(@artifact))
279
289
  if response.code == "200"
280
290
  File.write(File.expand_path(filename), response.body)
281
291
  else
@@ -283,6 +293,41 @@ module JenkinsApi
283
293
  end
284
294
  end
285
295
 
296
+ # Connects to the server and download all artifacts of a build to a specified location
297
+ #
298
+ # @param [String] job_name
299
+ # @param [String] dldir location to save artifacts
300
+ # @param [Integer] build_number optional, defaults to current build
301
+ # @returns [String, Array] list of retrieved artifacts
302
+ #
303
+ def get_artifacts(job_name, dldir, build_number = nil)
304
+ @artifacts = job.find_artifacts(job_name,build_number)
305
+ results = []
306
+ @artifacts.each do |artifact|
307
+ uri = URI.parse(artifact)
308
+ http = Net::HTTP.new(uri.host, uri.port)
309
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
310
+ http.use_ssl = @ssl
311
+ request = Net::HTTP::Get.new(uri.request_uri)
312
+ request.basic_auth(@username, @password)
313
+ response = http.request(request)
314
+ # we want every thing after the last 'build' in the path to become the filename
315
+ if artifact.include?('/build/')
316
+ filename = artifact.split("/build/").last.gsub('/','-')
317
+ else
318
+ filename = File.basename(artifact)
319
+ end
320
+ filename = File.join(dldir, filename)
321
+ results << filename
322
+ if response.code == "200"
323
+ File.write(File.expand_path(filename), response.body)
324
+ else
325
+ raise "Couldn't get the artifact #{artifact} for job #{job}"
326
+ end
327
+ end
328
+ results
329
+ end
330
+
286
331
  # Connects to the Jenkins server, sends the specified request and returns
287
332
  # the response.
288
333
  #
@@ -300,19 +345,26 @@ module JenkinsApi
300
345
  when 'http'
301
346
  http = Net::HTTP::Proxy(@proxy_ip, @proxy_port).new(@server_ip, @server_port)
302
347
  when 'socks'
303
- http = Net::HTTP::SOCKSProxy(@proxy_ip, @proxy_port).start(@server_ip, @server_port)
348
+ http = Net::HTTP::SOCKSProxy(@proxy_ip, @proxy_port).new(@server_ip, @server_port)
304
349
  else
305
- raise "unknwon proxy protocol: '#{@proxy_protocol}'"
350
+ raise "unknown proxy protocol: '#{@proxy_protocol}'"
306
351
  end
307
352
  else
308
353
  http = Net::HTTP.new(@server_ip, @server_port)
309
354
  end
310
355
 
311
- if @ssl
356
+ if @ssl && @pkcs_file_path
312
357
  http.use_ssl = true
358
+ pkcs12 =OpenSSL::PKCS12.new(File.binread(@pkcs_file_path), @pass_phrase!=nil ? @pass_phrase : "")
359
+ http.cert = pkcs12.certificate
360
+ http.key = pkcs12.key
313
361
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
314
- end
362
+ elsif @ssl
363
+ http.use_ssl = true
315
364
 
365
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
366
+ http.ca_file = @ca_file if @ca_file
367
+ end
316
368
  http.open_timeout = @http_open_timeout
317
369
  http.read_timeout = @http_read_timeout
318
370
 
@@ -490,7 +542,7 @@ module JenkinsApi
490
542
  @logger.info "Initializing Jenkins Update Center..."
491
543
  @logger.debug "Obtaining the JSON data for Update Center..."
492
544
  # TODO: Clean me up
493
- update_center_data = open("http://updates.jenkins-ci.org/update-center.json").read
545
+ update_center_data = open("https://updates.jenkins.io/current/update-center.json").read
494
546
  # The Jenkins mirror returns the data in the following format
495
547
  # updateCenter.post(
496
548
  # {.. JSON data...}
@@ -754,7 +806,7 @@ module JenkinsApi
754
806
  # the queue.
755
807
  when 200, 201, 302
756
808
  if to_send == "body" && send_json
757
- return JSON.parse(response.body)
809
+ return JSON.parse(response.body, max_nesting: false)
758
810
  elsif to_send == "body"
759
811
  return response.body
760
812
  elsif to_send == "code"
@@ -299,6 +299,16 @@ module JenkinsApi
299
299
  xml.description
300
300
  xml.keepDependencies "#{params[:keep_dependencies]}"
301
301
  xml.properties
302
+ #buildlogs related stuff
303
+ if params[:discard_old_builds]
304
+ xml.logRotator(:class => 'hudson.tasks.LogRotator') do
305
+ xml.daysToKeep params[:discard_old_builds][:daysToKeep] || -1
306
+ xml.numToKeep params[:discard_old_builds][:numToKeep] || -1
307
+ xml.artifactDaysToKeep params[:discard_old_builds][:artifactDaysToKeep] || -1
308
+ xml.artifactNumToKeep params[:discard_old_builds][:artifactNumToKeep] || -1
309
+ end
310
+ end
311
+
302
312
  # SCM related stuff
303
313
  if params[:scm_provider] == 'subversion'
304
314
  # Build subversion related XML portion
@@ -744,13 +754,30 @@ module JenkinsApi
744
754
  "not_run"
745
755
  when "aborted"
746
756
  "aborted"
757
+ when "disabled"
758
+ "disabled"
747
759
  else
748
760
  "invalid"
749
761
  end
750
762
  end
751
763
 
764
+ # Determine if the build is queued
765
+ #
766
+ # @param [String] job_name
767
+ #
768
+ # @return [Integer] build number if queued, or [Boolean] false if not queued
769
+ #
770
+ def queued?(job_name)
771
+ queue_result = @client.api_get_request("/job/#{path_encode job_name}")['inQueue']
772
+ if queue_result
773
+ return @client.api_get_request("/job/#{path_encode job_name}")['nextBuildNumber']
774
+ else
775
+ return queue_result
776
+ end
777
+ end
778
+
752
779
  # Obtain the current build status of the job
753
- # By defaule Jenkins returns the color of the job status icon
780
+ # By default Jenkins returns the color of the job status icon
754
781
  # This function translates the color into a meaningful status
755
782
  #
756
783
  # @param [String] job_name
@@ -1086,6 +1113,23 @@ module JenkinsApi
1086
1113
  nil
1087
1114
  end
1088
1115
 
1116
+ # Obtain the plugin results for a specific build of a job
1117
+ #
1118
+ # @param [String] job_name
1119
+ # @param [Number] build_num
1120
+ # @param [String] plugin_name
1121
+ #
1122
+ def get_plugin_results(job_name, build_num, plugin_name)
1123
+ build_num = get_current_build_number(job_name) if build_num == 0
1124
+ @logger.info "Obtaining the '#{plugin_name}' plugin results of '#{job_name}'" +
1125
+ " Build ##{build_num}"
1126
+ @client.api_get_request("/job/#{path_encode job_name}/#{build_num}/#{plugin_name}Result")
1127
+ rescue Exceptions::NotFound
1128
+ # Not found is acceptable, as not all builds will have plugin results
1129
+ # and this is what jenkins throws at us in that case
1130
+ nil
1131
+ end
1132
+
1089
1133
  # Obtain detailed build info for a job
1090
1134
  #
1091
1135
  # @param [String] job_name
@@ -1399,6 +1443,71 @@ module JenkinsApi
1399
1443
  post_config(job_name, xml_modified)
1400
1444
  end
1401
1445
 
1446
+ # Add upstream projects to a specific job given the job name,
1447
+ # projects to be added as upstream projects, and the threshold
1448
+ #
1449
+ # @param [String] job_name
1450
+ # @param [String] upstream_projects - separated with comma
1451
+ # @param [String] threshold - failure, success, or unstable
1452
+ # @param [Boolean] overwrite - true or false
1453
+ #
1454
+ # @return [String] response_code return code from HTTP POST
1455
+ #
1456
+ def add_upstream_projects(job_name,
1457
+ upstream_projects,
1458
+ threshold, overwrite = false)
1459
+ @logger.info "Adding #{upstream_projects.inspect} as upstream" +
1460
+ " projects for '#{job_name}' with the threshold of '#{threshold}'" +
1461
+ " and overwrite option of '#{overwrite}'"
1462
+ name, ord, col = get_threshold_params(threshold)
1463
+ xml = get_config(job_name)
1464
+ n_xml = Nokogiri::XML(xml)
1465
+ upstream_projects_node = n_xml.xpath("//upstreamProjects").first
1466
+ if upstream_projects_node
1467
+ if overwrite
1468
+ upstream_projects_node.content = "#{upstream_projects}"
1469
+ else
1470
+ to_replace = upstream_projects_node.content +
1471
+ ", #{upstream_projects}"
1472
+ upstream_projects_node.content = to_replace
1473
+ end
1474
+ else
1475
+ triggers_node = n_xml.xpath("//triggers").first
1476
+ reverse_build_trigger_node = triggers_node.add_child(
1477
+ "<jenkins.triggers.ReverseBuildTrigger/>"
1478
+ )
1479
+ reverse_build_trigger_node.first.add_child(
1480
+ "<spec/>"
1481
+ )
1482
+ reverse_build_trigger_node.first.add_child(
1483
+ "<upstreamProjects>#{upstream_projects}</upstreamProjects>"
1484
+ )
1485
+ threshold_node = reverse_build_trigger_node.first.add_child(
1486
+ "<threshold/>"
1487
+ )
1488
+ threshold_node.first.add_child(
1489
+ "<name>#{name}</name><ordinal>#{ord}</ordinal><color>#{col}</color>"
1490
+ )
1491
+ end
1492
+ xml_modified = n_xml.to_xml
1493
+ post_config(job_name, xml_modified)
1494
+ end
1495
+
1496
+ # Remove all upstream projects of a specific job
1497
+ #
1498
+ # @param [String] job_name
1499
+ #
1500
+ # @return [String] response_code return code from HTTP POST
1501
+ #
1502
+ def remove_upstream_projects(job_name)
1503
+ @logger.info "Removing the upstream projects of '#{job_name}'"
1504
+ xml = get_config(job_name)
1505
+ n_xml = Nokogiri::XML(xml)
1506
+ n_xml.search("//jenkins.triggers.ReverseBuildTrigger").remove
1507
+ xml_modified = n_xml.to_xml
1508
+ post_config(job_name, xml_modified)
1509
+ end
1510
+
1402
1511
  # Resctrict the given job to a specific node
1403
1512
  #
1404
1513
  # @param [String] job_name
@@ -1546,15 +1655,49 @@ module JenkinsApi
1546
1655
  #A Method to find artifacts path from the Current Build
1547
1656
  #
1548
1657
  # @param [String] job_name
1658
+ # @param [Integer] build_number
1659
+ # defaults to latest build
1549
1660
  #
1550
- def find_artifact(job_name)
1551
- current_build_number = get_current_build_number(job_name)
1552
- job_path = "job/#{path_encode job_name}/"
1553
- response_json = @client.api_get_request("/#{job_path}#{current_build_number}")
1554
- relative_build_path = response_json['artifacts'][0]['relativePath']
1555
- jenkins_path = response_json['url']
1556
- artifact_path = URI.escape("#{jenkins_path}artifact/#{relative_build_path}")
1557
- return artifact_path
1661
+ def find_artifact(job_name, build_number = 0)
1662
+ find_artifacts(job_name, build_number).first
1663
+ end
1664
+
1665
+ #A Method to check artifact exists path from the Current Build
1666
+ #
1667
+ # @param [String] job_name
1668
+ # @param [Integer] build_number
1669
+ # defaults to latest build
1670
+ #
1671
+ def artifact_exists?(job_name, build_number = 0)
1672
+ begin
1673
+ artifact_path(job_name: job_name, build_number: build_number)
1674
+
1675
+ return true
1676
+ rescue Exception => e
1677
+ return false
1678
+ end
1679
+ end
1680
+
1681
+ # Find the artifacts for build_number of job_name, defaulting to current job
1682
+ #
1683
+ # @param [String] job_name
1684
+ # @param [Integer] build_number Optional build number
1685
+ # @return [String, Hash] JSON response from Jenkins
1686
+ #
1687
+ def find_artifacts(job_name, build_number = nil)
1688
+ response_json = get_build_details(job_name, build_number)
1689
+ artifact_path(build_details: response_json).map do |p|
1690
+ path_encode("#{response_json['url']}artifact/#{p['relativePath']}")
1691
+ end
1692
+ end
1693
+
1694
+ # Find the artifacts for the current job
1695
+ #
1696
+ # @param [String] job_name
1697
+ # @return [String, Hash] JSON response from Jenkins
1698
+ #
1699
+ def find_latest_artifacts(job_name)
1700
+ find_artifacts(job_name)
1558
1701
  end
1559
1702
 
1560
1703
  private
@@ -1795,6 +1938,29 @@ module JenkinsApi
1795
1938
  return nil unless tree_value
1796
1939
  "tree=#{tree_value}"
1797
1940
  end
1941
+
1942
+ # This private method gets the artifact path or throws an exception
1943
+ #
1944
+ # @param [Hash] job_name, build_number or build_details object
1945
+ #
1946
+ def artifact_path(params)
1947
+ job_name = params[:job_name]
1948
+ build_number = params[:build_number] || 0
1949
+ build_details = params[:build_details]
1950
+
1951
+ build_details = get_build_details(job_name, build_number) if build_details.nil?
1952
+ artifacts = build_details['artifacts']
1953
+ artifact_paths = []
1954
+
1955
+ if artifacts && artifacts.any?
1956
+ artifact_paths = artifacts.find_all{ |a| a.key?('relativePath') }
1957
+ end
1958
+
1959
+ if artifact_paths.empty?
1960
+ raise "No artifacts found."
1961
+ end
1962
+ artifact_paths
1963
+ end
1798
1964
  end
1799
1965
  end
1800
1966
  end
@@ -211,18 +211,42 @@ module JenkinsApi
211
211
  list.each { |node| delete(node) unless node == "master" }
212
212
  end
213
213
 
214
+ # This method returns two lists 1) nodes online 2) nodes offline
215
+ #
216
+ # @param [String] filter a regex to filter node names
217
+ # @param [Bool] ignorecase whether to be case sensitive or not
218
+ #
219
+ def online_offline_lists(filter = nil, ignorecase = true)
220
+ @logger.info "Obtaining nodes from jenkins matching filter '#{filter}'"
221
+ offline_node_names = []
222
+ online_node_names = []
223
+ response_json = @client.api_get_request("/computer")
224
+ response_json["computer"].each do |computer|
225
+ if computer["displayName"] =~ /#{filter}/i
226
+ if computer["offline"] == true
227
+ offline_node_names << computer["displayName"]
228
+ else
229
+ online_node_names << computer["displayName"]
230
+ end
231
+ end
232
+ end
233
+ return online_node_names, offline_node_names
234
+ end
235
+
214
236
  # This method lists all nodes
215
237
  #
216
238
  # @param [String] filter a regex to filter node names
217
239
  # @param [Bool] ignorecase whether to be case sensitive or not
218
240
  #
219
- def list(filter = nil, ignorecase = true)
241
+ def list(filter = nil, ignorecase = true, slaveonly = false)
220
242
  @logger.info "Obtaining nodes from jenkins matching filter '#{filter}'"
221
243
  node_names = []
222
244
  response_json = @client.api_get_request("/computer")
223
245
  response_json["computer"].each do |computer|
224
246
  if computer["displayName"] =~ /#{filter}/i
225
- node_names << computer["displayName"]
247
+ unless slaveonly && computer["displayName"] == "master"
248
+ node_names << computer["displayName"]
249
+ end
226
250
  end
227
251
  end
228
252
  node_names
@@ -148,7 +148,7 @@ module JenkinsApi
148
148
  # "pinned"=>true,
149
149
  # "shortName"=>"ldap",
150
150
  # "supportsDynamicLoad"=>"MAYBE",
151
- # "url"=>"http://wiki.jenkins-ci.org/display/JENKINS/LDAP+Plugin",
151
+ # "url"=>"https://wiki.jenkins.io/display/JENKINS/LDAP+Plugin",
152
152
  # "version"=>"1.5"
153
153
  # }
154
154
  #
@@ -256,7 +256,7 @@ module JenkinsApi
256
256
  # => {
257
257
  # "name"=>"status-view",
258
258
  # "sourceId"=>"default",
259
- # "url"=>"http://updates.jenkins-ci.org/download/plugins/status-view/1.0/status-view.hpi",
259
+ # "url"=>"https://updates.jenkins.io/download/plugins/status-view/1.0/status-view.hpi",
260
260
  # "version"=>"1.0",
261
261
  # "categories"=>["ui"],
262
262
  # "compatibleSinceVersion"=>nil,
@@ -266,7 +266,7 @@ module JenkinsApi
266
266
  # "installed"=>nil, "neededDependencies"=>[],
267
267
  # "requiredCore"=>"1.342",
268
268
  # "title"=>"Status View Plugin",
269
- # "wiki"=>"https://wiki.jenkins-ci.org/display/JENKINS/Status+View+Plugin"
269
+ # "wiki"=>"https://wiki.jenkins.io/display/JENKINS/Status+View+Plugin"
270
270
  # }
271
271
  #
272
272
  def get_available_info(plugin)
@@ -0,0 +1,67 @@
1
+ #
2
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
3
+ # of this software and associated documentation files (the "Software"), to deal
4
+ # in the Software without restriction, including without limitation the rights
5
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6
+ # copies of the Software, and to permit persons to whom the Software is
7
+ # furnished to do so, subject to the following conditions:
8
+ #
9
+ # The above copyright notice and this permission notice shall be included in
10
+ # all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18
+ # THE SOFTWARE.
19
+ #
20
+
21
+ require 'jenkins_api_client/urihelper'
22
+
23
+ module JenkinsApi
24
+ class Client
25
+ # This class communicates with Jenkins API at the root address to obtain details
26
+ # on the page displayed to users on the Jenkins' 'homepage,' and other
27
+ # data items such as quietingDown
28
+ class Root
29
+ include JenkinsApi::UriHelper
30
+
31
+ # Initializes a new root object
32
+ #
33
+ # @param client [Client] the client object
34
+ #
35
+ # @return [Root] the root object
36
+ #
37
+ def initialize(client)
38
+ @client = client
39
+ @logger = @client.logger
40
+ end
41
+
42
+ # Return a string representation of the object
43
+ #
44
+ def to_s
45
+ "#<JenkinsApi::Client::Root>"
46
+ end
47
+
48
+ # Check if Jenkins is in shutdown mode
49
+ #
50
+ # @return [Boolean] true if server in shutdown mode
51
+ #
52
+ def quieting_down?
53
+ response_json = @client.api_get_request('', 'tree=quietingDown')
54
+ response_json['quietingDown']
55
+ end
56
+
57
+ # Get message displayed to users on the homepage
58
+ #
59
+ # @return [String] description - message displayed to users
60
+ #
61
+ def description
62
+ response_json = @client.api_get_request('', 'tree=description')
63
+ response_json['description']
64
+ end
65
+ end
66
+ end
67
+ end
@@ -54,13 +54,20 @@ module JenkinsApi
54
54
  @client.api_post_request("/quietDown")
55
55
  end
56
56
 
57
- # Cancels the quiet doen request sent to the server.
57
+ # Cancels the quiet down request sent to the server.
58
58
  #
59
59
  def cancel_quiet_down
60
60
  @logger.info "Cancelling jenkins form quiet down..."
61
61
  @client.api_post_request("/cancelQuietDown")
62
62
  end
63
63
 
64
+ # Checks if server is in quiet down mode.
65
+ #
66
+ def check_quiet_down?
67
+ @logger.info "Checking if jenkins is in quiet down mode..."
68
+ @client.root.quieting_down?
69
+ end
70
+
64
71
  # Restarts the Jenkins server
65
72
  #
66
73
  # @param [Boolean] force whether to force restart or wait till all
@@ -1,4 +1,5 @@
1
1
  require 'uri'
2
+ require 'addressable/uri'
2
3
 
3
4
  module JenkinsApi
4
5
  module UriHelper
@@ -11,7 +12,7 @@ module JenkinsApi
11
12
  # Encode a string for use in the hiearchical part of an URL
12
13
  #
13
14
  def path_encode(path)
14
- URI.escape(path.encode(Encoding::UTF_8))
15
+ Addressable::URI.escape(path.encode(Encoding::UTF_8))
15
16
  end
16
17
  end
17
18
  end
@@ -22,15 +22,7 @@
22
22
 
23
23
  module JenkinsApi
24
24
  class Client
25
- # Major version of the gem
26
- MAJOR = 1
27
- # Minor version of the gem
28
- MINOR = 5
29
- # Tiny version of the gem used for patches
30
- TINY = 3
31
- # Used for pre-releases
32
- PRE = nil
33
25
  # Version String of Jenkins API Client.
34
- VERSION = [MAJOR, MINOR, TINY, PRE].compact.join('.')
26
+ VERSION = "2.1.0"
35
27
  end
36
28
  end
@@ -257,6 +257,38 @@ module JenkinsApi
257
257
  @client.api_post_request(post_msg)
258
258
  end
259
259
 
260
+ # List (sub-)views in a view
261
+ #
262
+ # @param [String] view_name
263
+ #
264
+ # @return [Array] view_names list of (sub-)views in the specified view
265
+ #
266
+ def list_views(view_name)
267
+ @logger.info "Obtaining the views present in view '#{view_name}'"
268
+ view_names = []
269
+ raise "The view #{view_name} doesn't exists on the server"\
270
+ unless exists?(view_name)
271
+ response_json = @client.api_get_request("/view/#{path_encode view_name}")
272
+ response_json["views"].each do |view|
273
+ view_names << view["name"]
274
+ end
275
+ view_names
276
+ end
277
+
278
+ # List (sub-)views in view along with their details
279
+ #
280
+ # @param [String] view_name
281
+ #
282
+ # @return [Array<Hash>] the details of (sub-)views in the specified view
283
+ #
284
+ def list_views_with_details(view_name)
285
+ @logger.info "Obtaining the views present in view '#{view_name}'"
286
+ raise "The view #{view_name} doesn't exists on the server"\
287
+ unless exists?(view_name)
288
+ response_json = @client.api_get_request("/view/#{path_encode view_name}")
289
+ response_json["views"]
290
+ end
291
+
260
292
  # Obtain the configuration stored in config.xml of a specific view
261
293
  #
262
294
  # @param [String] view_name
@@ -30,6 +30,7 @@ require 'jenkins_api_client/view'
30
30
  require 'jenkins_api_client/build_queue'
31
31
  require 'jenkins_api_client/plugin_manager'
32
32
  require 'jenkins_api_client/user'
33
+ require 'jenkins_api_client/root'
33
34
 
34
35
  require 'jenkins_api_client/cli/helper'
35
36
  require 'jenkins_api_client/cli/base'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jenkins_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.3
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kannan Manickam
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-30 00:00:00.000000000 Z
11
+ date: 2023-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: addressable
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.7'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.7'
97
111
  description: |2-
98
112
 
99
113
  This is a simple and easy-to-use Jenkins Api client with features focused on
@@ -124,32 +138,33 @@ files:
124
138
  - lib/jenkins_api_client/plugin_settings/collection.rb
125
139
  - lib/jenkins_api_client/plugin_settings/hipchat.rb
126
140
  - lib/jenkins_api_client/plugin_settings/workspace_cleanup.rb
141
+ - lib/jenkins_api_client/root.rb
127
142
  - lib/jenkins_api_client/system.rb
128
143
  - lib/jenkins_api_client/urihelper.rb
129
144
  - lib/jenkins_api_client/user.rb
130
145
  - lib/jenkins_api_client/version.rb
131
146
  - lib/jenkins_api_client/view.rb
132
147
  homepage: https://github.com/arangamani/jenkins_api_client
133
- licenses: []
148
+ licenses:
149
+ - MIT
134
150
  metadata: {}
135
- post_install_message:
151
+ post_install_message:
136
152
  rdoc_options: []
137
153
  require_paths:
138
154
  - lib
139
155
  required_ruby_version: !ruby/object:Gem::Requirement
140
156
  requirements:
141
- - - "~>"
157
+ - - ">="
142
158
  - !ruby/object:Gem::Version
143
- version: '2.1'
159
+ version: '2.7'
144
160
  required_rubygems_version: !ruby/object:Gem::Requirement
145
161
  requirements:
146
162
  - - ">="
147
163
  - !ruby/object:Gem::Version
148
164
  version: '0'
149
165
  requirements: []
150
- rubyforge_project:
151
- rubygems_version: 2.2.5
152
- signing_key:
166
+ rubygems_version: 3.3.3
167
+ signing_key:
153
168
  specification_version: 4
154
169
  summary: Jenkins JSON API Client
155
170
  test_files: []