jenkins_api_client 1.5.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/jenkins_api_client.gemspec +3 -6
- data/lib/jenkins_api_client/client.rb +63 -11
- data/lib/jenkins_api_client/job.rb +175 -9
- data/lib/jenkins_api_client/node.rb +26 -2
- data/lib/jenkins_api_client/plugin_manager.rb +3 -3
- data/lib/jenkins_api_client/root.rb +67 -0
- data/lib/jenkins_api_client/system.rb +8 -1
- data/lib/jenkins_api_client/urihelper.rb +2 -1
- data/lib/jenkins_api_client/version.rb +1 -9
- data/lib/jenkins_api_client/view.rb +32 -0
- data/lib/jenkins_api_client.rb +1 -0
- metadata +22 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: aadb30157bc60ba6690d00e65c6f4189c9b67a99d28b237b1d6109eba3fb96dc
|
4
|
+
data.tar.gz: 56d061edfd578401afe42ab0ed595db447945a6dc09e36fabc6ca22dd5413af4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78c788fc101b7d84afa16a832bbb427c8edb56b9c4625c5ec8a2f494404eba2ebb5d57677fef03a173d7ae1bd6a1fe2916baf101bb1d1fb6642317a183926665
|
7
|
+
data.tar.gz: 04e8ab2ff60a70604b082cfa10a2f4cbafd11387893eeb39a8c45fc08291cde4f71f4c1fa4e7616e3d593e6a193006163a98d16162a2800cc795c48807d7dd4b
|
data/jenkins_api_client.gemspec
CHANGED
@@ -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 =
|
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
|
-
|
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
|
#
|
@@ -302,17 +347,24 @@ module JenkinsApi
|
|
302
347
|
when 'socks'
|
303
348
|
http = Net::HTTP::SOCKSProxy(@proxy_ip, @proxy_port).start(@server_ip, @server_port)
|
304
349
|
else
|
305
|
-
raise "
|
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
|
-
|
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("
|
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...}
|
@@ -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
|
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
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
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
|
-
|
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"=>"
|
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"=>"
|
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
|
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
|
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 =
|
26
|
+
VERSION = "2.0.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
|
data/lib/jenkins_api_client.rb
CHANGED
@@ -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:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kannan Manickam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-20 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,13 +138,15 @@ 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
151
|
post_install_message:
|
136
152
|
rdoc_options: []
|
@@ -138,17 +154,16 @@ 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.
|
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
|
-
|
151
|
-
rubygems_version: 2.2.5
|
166
|
+
rubygems_version: 3.1.6
|
152
167
|
signing_key:
|
153
168
|
specification_version: 4
|
154
169
|
summary: Jenkins JSON API Client
|