jenkins_api_client 0.14.1 → 1.0.0.alpha.1
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.
- data/.travis.yml +1 -1
- data/CONTRIBUTORS.md +2 -0
- data/Gemfile +1 -0
- data/README.md +1 -1
- data/jenkins_api_client.gemspec +1 -0
- data/lib/jenkins_api_client.rb +1 -0
- data/lib/jenkins_api_client/client.rb +15 -3
- data/lib/jenkins_api_client/exceptions.rb +25 -16
- data/lib/jenkins_api_client/job.rb +46 -18
- data/lib/jenkins_api_client/plugin_manager.rb +460 -0
- data/lib/jenkins_api_client/version.rb +4 -4
- data/spec/func_tests/plugin_spec.rb.pending +148 -0
- data/spec/unit_tests/fixtures/files/available_plugins.json +1 -0
- data/spec/unit_tests/fixtures/files/installed_plugins.json +1 -0
- data/spec/unit_tests/fixtures/files/updatable_plugins.json +1 -0
- data/spec/unit_tests/plugin_spec.rb +165 -0
- data/spec/unit_tests/spec_helper.rb +11 -1
- data/travis/hudson.model.UpdateCenter.xml +7 -0
- data/travis/setup.sh +1 -0
- metadata +29 -6
data/.travis.yml
CHANGED
data/CONTRIBUTORS.md
CHANGED
@@ -11,3 +11,5 @@ Thank you very much to all who contributed to this project.
|
|
11
11
|
* [rubytester](https://github.com/rubytester)
|
12
12
|
* [dougforpres](https://github.com/dougforpres)
|
13
13
|
* [brettporter](https://github.com/brettporter)
|
14
|
+
* [riywo](https://github.com/riywo)
|
15
|
+
* [bobbrez](https://github.com/bobbrez)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -102,7 +102,7 @@ puts @client.job.list_all
|
|
102
102
|
### Chaining and Building Jobs
|
103
103
|
|
104
104
|
Sometimes we want certain jobs to be added as downstream projects and run them
|
105
|
-
|
105
|
+
sequentially. The following example will explain how this could be done.
|
106
106
|
|
107
107
|
```ruby
|
108
108
|
require 'jenkins_api_client'
|
data/jenkins_api_client.gemspec
CHANGED
@@ -40,6 +40,7 @@ Gem::Specification.new do |s|
|
|
40
40
|
"lib/jenkins_api_client/exceptions.rb",
|
41
41
|
"lib/jenkins_api_client/job.rb",
|
42
42
|
"lib/jenkins_api_client/node.rb",
|
43
|
+
"lib/jenkins_api_client/plugin_manager.rb",
|
43
44
|
"lib/jenkins_api_client/system.rb",
|
44
45
|
"lib/jenkins_api_client/user.rb",
|
45
46
|
"lib/jenkins_api_client/version.rb",
|
data/lib/jenkins_api_client.rb
CHANGED
@@ -28,6 +28,7 @@ require 'jenkins_api_client/node'
|
|
28
28
|
require 'jenkins_api_client/system'
|
29
29
|
require 'jenkins_api_client/view'
|
30
30
|
require 'jenkins_api_client/build_queue'
|
31
|
+
require 'jenkins_api_client/plugin_manager'
|
31
32
|
require 'jenkins_api_client/user'
|
32
33
|
|
33
34
|
require 'jenkins_api_client/cli/helper'
|
@@ -212,6 +212,15 @@ module JenkinsApi
|
|
212
212
|
JenkinsApi::Client::BuildQueue.new(self)
|
213
213
|
end
|
214
214
|
|
215
|
+
# Creates an instance to the PluginManager by passing a reference to self
|
216
|
+
#
|
217
|
+
# @return [JenkinsApi::Client::PluginManager] an object to PluginManager
|
218
|
+
# subclass
|
219
|
+
#
|
220
|
+
def plugin
|
221
|
+
JenkinsApi::Client::PluginManager.new(self)
|
222
|
+
end
|
223
|
+
|
215
224
|
# Creates an instance of the User class by passing a reference to self
|
216
225
|
#
|
217
226
|
# @return [JenkinsApi::Client::User] An object of User subclass
|
@@ -288,8 +297,8 @@ module JenkinsApi
|
|
288
297
|
# @return [Net::HTTP::Response] Response from Jenkins for "/"
|
289
298
|
#
|
290
299
|
def get_root
|
291
|
-
@logger.info "GET /"
|
292
|
-
request = Net::HTTP::Get.new("/")
|
300
|
+
@logger.info "GET #{@jenkins_path}/"
|
301
|
+
request = Net::HTTP::Get.new("#{@jenkins_path}/")
|
293
302
|
make_http_request(request)
|
294
303
|
end
|
295
304
|
|
@@ -633,7 +642,10 @@ module JenkinsApi
|
|
633
642
|
when 404
|
634
643
|
raise Exceptions::NotFound.new @logger
|
635
644
|
when 500
|
636
|
-
|
645
|
+
matched = response.body.match(/Exception: (.*)<br>/)
|
646
|
+
api_message = matched[1] unless matched.nil?
|
647
|
+
@logger.debug "API message: #{api_message}"
|
648
|
+
raise Exceptions::InternalServerError.new(@logger, api_message)
|
637
649
|
when 503
|
638
650
|
raise Exceptions::ServiceUnavailable.new @logger
|
639
651
|
else
|
@@ -41,8 +41,8 @@ module JenkinsApi
|
|
41
41
|
#
|
42
42
|
class NothingSubmitted < ApiException
|
43
43
|
def initialize(logger, message = "", log_level = Logger::ERROR)
|
44
|
-
|
45
|
-
super(logger,
|
44
|
+
message = "Nothing is submitted." if message.empty?
|
45
|
+
super(logger, message)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -80,8 +80,8 @@ module JenkinsApi
|
|
80
80
|
#
|
81
81
|
class Unauthorized < ApiException
|
82
82
|
def initialize(logger, message = "", log_level = Logger::ERROR)
|
83
|
-
|
84
|
-
super(logger,
|
83
|
+
message = "Invalid credentials are provided." if message.empty?
|
84
|
+
super(logger, message, Logger::FATAL)
|
85
85
|
end
|
86
86
|
end
|
87
87
|
# Support for backward compatibility
|
@@ -158,8 +158,8 @@ module JenkinsApi
|
|
158
158
|
#
|
159
159
|
class CrumbNotFound < NotFound
|
160
160
|
def initialize(logger, message = "", log_level = Logger::ERROR)
|
161
|
-
|
162
|
-
super(logger,
|
161
|
+
message = "No crumb available on the server." if message.empty?
|
162
|
+
super(logger, message)
|
163
163
|
end
|
164
164
|
end
|
165
165
|
# Support for backward compatibility
|
@@ -200,10 +200,10 @@ module JenkinsApi
|
|
200
200
|
#
|
201
201
|
class InternalServerError < ApiException
|
202
202
|
def initialize(logger, message = "", log_level = Logger::ERROR)
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
super(logger,
|
203
|
+
message = "Internel Server Error. Perhaps the in-memory configuration" +
|
204
|
+
" Jenkins is different from the disk configuration. Please try to" +
|
205
|
+
" reload the configuration" if message.empty?
|
206
|
+
super(logger, message)
|
207
207
|
end
|
208
208
|
end
|
209
209
|
# Support for backward compatibility
|
@@ -214,10 +214,10 @@ module JenkinsApi
|
|
214
214
|
#
|
215
215
|
class ServiceUnavailable < ApiException
|
216
216
|
def initialize(logger, message = "", log_level = Logger::ERROR)
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
super(logger,
|
217
|
+
message = "Jenkins is being reloaded or restarted. Please wait till" +
|
218
|
+
" Jenkins is completely back online. This can be" +
|
219
|
+
" programatically achieved by System#wait_for_ready" if message.empty?
|
220
|
+
super(logger, message)
|
221
221
|
end
|
222
222
|
end
|
223
223
|
# Support for backward compatibility
|
@@ -227,11 +227,20 @@ module JenkinsApi
|
|
227
227
|
#
|
228
228
|
class CLIError < ApiException
|
229
229
|
def initialize(logger, message = "", log_level = Logger::ERROR)
|
230
|
-
|
231
|
-
super(logger,
|
230
|
+
message = "Unable to execute the command." if message.empty?
|
231
|
+
super(logger, message)
|
232
232
|
end
|
233
233
|
end
|
234
234
|
# Support for backward compatibility
|
235
235
|
CLIException = CLIError
|
236
|
+
|
237
|
+
# Exception when a particular plugin is not found
|
238
|
+
#
|
239
|
+
class PluginNotFound < NotFound
|
240
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
241
|
+
message = "The specified plugin is not found" if message.empty?
|
242
|
+
super(logger, message)
|
243
|
+
end
|
244
|
+
end
|
236
245
|
end
|
237
246
|
end
|
@@ -197,7 +197,7 @@ module JenkinsApi
|
|
197
197
|
# Update a job with params given as a hash instead of the xml. For the
|
198
198
|
# parameter description see #create_or_update_freestyle
|
199
199
|
#
|
200
|
-
# @param params [Hash]
|
200
|
+
# @param params [Hash] parameters to update a freestyle project
|
201
201
|
#
|
202
202
|
# @see #create_or_update_freestyle
|
203
203
|
# @see #update
|
@@ -334,7 +334,7 @@ module JenkinsApi
|
|
334
334
|
# @option params [String] :name Name of the job
|
335
335
|
# @option params [String] :notification_email Email address to send
|
336
336
|
# @option params [Boolean] :notification_email_for_every_unstable
|
337
|
-
#
|
337
|
+
# Send email notification email for every unstable build
|
338
338
|
#
|
339
339
|
def add_email_notification(params)
|
340
340
|
raise "No job name specified" unless params[:name]
|
@@ -405,7 +405,9 @@ module JenkinsApi
|
|
405
405
|
|
406
406
|
# Delete a job given the name
|
407
407
|
#
|
408
|
-
# @param [String]
|
408
|
+
# @param job_name [String] the name of the job to delete
|
409
|
+
#
|
410
|
+
# @return [String] the response from the HTTP POST request
|
409
411
|
#
|
410
412
|
def delete(job_name)
|
411
413
|
@logger.info "Deleting job '#{job_name}'"
|
@@ -424,7 +426,9 @@ module JenkinsApi
|
|
424
426
|
|
425
427
|
# Wipe out the workspace for a job given the name
|
426
428
|
#
|
427
|
-
# @param [String]
|
429
|
+
# @param job_name [String] the name of the job to wipe out the workspace
|
430
|
+
#
|
431
|
+
# @return [String] response from the HTTP POST request
|
428
432
|
#
|
429
433
|
def wipe_out_workspace(job_name)
|
430
434
|
@logger.info "Wiping out the workspace of job '#{job_name}'"
|
@@ -436,8 +440,8 @@ module JenkinsApi
|
|
436
440
|
# is specified. The build will be stopped only if it was
|
437
441
|
# in 'running' state.
|
438
442
|
#
|
439
|
-
# @param [String]
|
440
|
-
# @param [Number]
|
443
|
+
# @param job_name [String] the name of the job to stop the build
|
444
|
+
# @param build_number [Number] the build number to stop
|
441
445
|
#
|
442
446
|
def stop_build(job_name, build_number = 0)
|
443
447
|
build_number = get_current_build_number(job_name) if build_number == 0
|
@@ -451,11 +455,15 @@ module JenkinsApi
|
|
451
455
|
@client.api_post_request("/job/#{job_name}/#{build_number}/stop")
|
452
456
|
end
|
453
457
|
end
|
458
|
+
alias_method :stop, :stop_build
|
459
|
+
alias_method :abort, :stop_build
|
454
460
|
|
455
461
|
# Re-create the same job
|
456
462
|
# This is a hack to clear any existing builds
|
457
463
|
#
|
458
|
-
# @param [String]
|
464
|
+
# @param job_name [String] the name of the job to recreate
|
465
|
+
#
|
466
|
+
# @return [String] the response from the HTTP POST request
|
459
467
|
#
|
460
468
|
def recreate(job_name)
|
461
469
|
@logger.info "Recreating job '#{job_name}'"
|
@@ -466,8 +474,10 @@ module JenkinsApi
|
|
466
474
|
|
467
475
|
# Copy a job
|
468
476
|
#
|
469
|
-
# @param [String]
|
470
|
-
# @param [String]
|
477
|
+
# @param from_job_name [String] the name of the job to copy from
|
478
|
+
# @param to_job_name [String] the name of the job to copy to
|
479
|
+
#
|
480
|
+
# @return [String] the response from the HTTP POST request
|
471
481
|
#
|
472
482
|
def copy(from_job_name, to_job_name=nil)
|
473
483
|
to_job_name = "copy_of_#{from_job_name}" if to_job_name.nil?
|
@@ -481,7 +491,7 @@ module JenkinsApi
|
|
481
491
|
#
|
482
492
|
# @param [String] job_name Name of the Jenkins job
|
483
493
|
# @param [Number] build_num Specific build number to obtain the
|
484
|
-
#
|
494
|
+
# console output from. Default is the recent build
|
485
495
|
# @param [Number] start start offset to get only a portion of the text
|
486
496
|
# @param [String] mode Mode of text output. 'text' or 'html'
|
487
497
|
#
|
@@ -520,6 +530,8 @@ module JenkinsApi
|
|
520
530
|
|
521
531
|
# List all jobs on the Jenkins CI server
|
522
532
|
#
|
533
|
+
# @return [Array<String>] the names of all jobs in jenkins
|
534
|
+
#
|
523
535
|
def list_all
|
524
536
|
response_json = @client.api_get_request("", "tree=jobs[name]")["jobs"]
|
525
537
|
response_json.map { |job| job["name"] }.sort
|
@@ -527,7 +539,9 @@ module JenkinsApi
|
|
527
539
|
|
528
540
|
# Checks if the given job exists in Jenkins
|
529
541
|
#
|
530
|
-
# @param [String]
|
542
|
+
# @param job_name [String] the name of the job to check
|
543
|
+
#
|
544
|
+
# @return [Boolean] whether the job exists in jenkins or not
|
531
545
|
#
|
532
546
|
def exists?(job_name)
|
533
547
|
list(job_name).include?(job_name)
|
@@ -536,8 +550,12 @@ module JenkinsApi
|
|
536
550
|
# List all Jobs matching the given status
|
537
551
|
# You can optionally pass in jobs list to filter the status from
|
538
552
|
#
|
539
|
-
# @param [String] status
|
540
|
-
# @param [Array]
|
553
|
+
# @param status [String] the job status to filter
|
554
|
+
# @param jobs [Array<String>] if specified this array will be used for
|
555
|
+
# filtering by the status otherwise the filtering will be done using
|
556
|
+
# all jobs available in jenkins
|
557
|
+
#
|
558
|
+
# @return [Array<String>] filtered jobs
|
541
559
|
#
|
542
560
|
def list_by_status(status, jobs = [])
|
543
561
|
jobs = list_all if jobs.empty?
|
@@ -555,8 +573,10 @@ module JenkinsApi
|
|
555
573
|
|
556
574
|
# List all jobs that match the given regex
|
557
575
|
#
|
558
|
-
# @param [String]
|
559
|
-
# @param [Boolean]
|
576
|
+
# @param filter [String] a regular expression or a string to filter jobs
|
577
|
+
# @param ignorecase [Boolean] whether to ignore case or not
|
578
|
+
#
|
579
|
+
# @return [Array<String>] jobs matching the given pattern
|
560
580
|
#
|
561
581
|
def list(filter, ignorecase = true)
|
562
582
|
@logger.info "Obtaining jobs matching filter '#{filter}'"
|
@@ -574,6 +594,8 @@ module JenkinsApi
|
|
574
594
|
|
575
595
|
# List all jobs on the Jenkins CI server along with their details
|
576
596
|
#
|
597
|
+
# @return [Array<Hash>] the details of all jobs in jenkins
|
598
|
+
#
|
577
599
|
def list_all_with_details
|
578
600
|
@logger.info "Obtaining the details of all jobs"
|
579
601
|
response_json = @client.api_get_request("")
|
@@ -582,7 +604,9 @@ module JenkinsApi
|
|
582
604
|
|
583
605
|
# List details of a specific job
|
584
606
|
#
|
585
|
-
# @param [String]
|
607
|
+
# @param job_name [String] the name of the job to obtain the details from
|
608
|
+
#
|
609
|
+
# @return [Hash] the details of the specified job
|
586
610
|
#
|
587
611
|
def list_details(job_name)
|
588
612
|
@logger.info "Obtaining the details of '#{job_name}'"
|
@@ -591,7 +615,8 @@ module JenkinsApi
|
|
591
615
|
|
592
616
|
# List upstream projects of a specific job
|
593
617
|
#
|
594
|
-
# @param [String]
|
618
|
+
# @param job_name [String] the name of the job to obtain upstream
|
619
|
+
# projects for
|
595
620
|
#
|
596
621
|
def get_upstream_projects(job_name)
|
597
622
|
@logger.info "Obtaining the upstream projects of '#{job_name}'"
|
@@ -601,7 +626,8 @@ module JenkinsApi
|
|
601
626
|
|
602
627
|
# List downstream projects of a specific job
|
603
628
|
#
|
604
|
-
# @param [String]
|
629
|
+
# @param job_name [String] the name of the job to obtain downstream
|
630
|
+
# projects for
|
605
631
|
#
|
606
632
|
def get_downstream_projects(job_name)
|
607
633
|
@logger.info "Obtaining the down stream projects of '#{job_name}'"
|
@@ -660,6 +686,7 @@ module JenkinsApi
|
|
660
686
|
response_json = @client.api_get_request("/job/#{job_name}")
|
661
687
|
color_to_status(response_json["color"])
|
662
688
|
end
|
689
|
+
alias_method :status, :get_current_build_status
|
663
690
|
|
664
691
|
# Obtain the current build number of the given job
|
665
692
|
# This function returns nil if there were no builds for the given job.
|
@@ -672,6 +699,7 @@ module JenkinsApi
|
|
672
699
|
@logger.info "Obtaining the current build number of '#{job_name}'"
|
673
700
|
@client.api_get_request("/job/#{job_name}")['nextBuildNumber'].to_i - 1
|
674
701
|
end
|
702
|
+
alias_method :build_number, :get_current_build_number
|
675
703
|
|
676
704
|
# Build a job given the name of the job
|
677
705
|
# You can optionally pass in a list of params for Jenkins to use for
|
@@ -0,0 +1,460 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012-2013 Kannan Manickam <arangamani.kannan@gmail.com>
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
module JenkinsApi
|
24
|
+
class Client
|
25
|
+
# This classes communicates with the /pluginManager API for listing
|
26
|
+
# installed plugins, installing new plgins through hacks, and performing a
|
27
|
+
# lot of operations on installed plugins. It also gives the ability to
|
28
|
+
# obtain the details about available plugins in Jenkins update center by
|
29
|
+
# commmunicating with /updateCenter API.
|
30
|
+
#
|
31
|
+
class PluginManager
|
32
|
+
|
33
|
+
# Initializes a new PluginManager object.
|
34
|
+
#
|
35
|
+
# @param [Object] client a reference to Client
|
36
|
+
#
|
37
|
+
def initialize(client)
|
38
|
+
@client = client
|
39
|
+
@logger = @client.logger
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a string representation of PluginManager class.
|
43
|
+
#
|
44
|
+
def to_s
|
45
|
+
"#<JenkinsApi::Client::PluginManager>"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Defines a method to perform the given action on plugin(s)
|
49
|
+
#
|
50
|
+
# @param action [Symbol] the action to perform
|
51
|
+
# @param post_endpoint [Symbol] the endpoint in the POST request for the
|
52
|
+
# action
|
53
|
+
#
|
54
|
+
def self.plugin_action_method(action, post_endpoint)
|
55
|
+
define_method(action) do |plugins|
|
56
|
+
plugins = [plugins] unless plugins.is_a?(Array)
|
57
|
+
@logger.info "Performing '#{action}' on plugins: #{plugins.inspect}"
|
58
|
+
plugins.each do |plugin|
|
59
|
+
@client.api_post_request(
|
60
|
+
"/pluginManager/plugin/#{plugin}/#{post_endpoint}"
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Obtains the list of installed plugins from Jenkins along with their
|
67
|
+
# version numbers with optional filters
|
68
|
+
#
|
69
|
+
# @param filters [Hash] optional filters to apply. Use symbols for filter
|
70
|
+
# keys
|
71
|
+
#
|
72
|
+
# @option filters [Boolean] :active filter active/non-active plugins
|
73
|
+
# @option filters [Boolean] :bundled filter bundled/non-bundled plugins
|
74
|
+
# @option filters [Boolean] :deleted filter deleted/available plugins
|
75
|
+
# @option filters [Boolean] :downgradable filter downgradable plugins
|
76
|
+
# @option filters [Boolean] :enabled filter enabled/disabled plugins
|
77
|
+
# @option filters [Boolean] :hasUpdate filter plugins that has update
|
78
|
+
# available. Note that 'U' is capitalized in hasUpdate.
|
79
|
+
# @option filters [Boolean] :pinned filter pinned/un-pinned plugins
|
80
|
+
#
|
81
|
+
# @return [Hash<String, String>] installed plugins and their versions
|
82
|
+
# matching the filter provided. returns an empty hash if there are no
|
83
|
+
# plugins matched the filters or no plugins are installed in jenkins.
|
84
|
+
#
|
85
|
+
# @example Listing installed plugins from jenkins
|
86
|
+
# >> @client.plugin.list_installed
|
87
|
+
# => {
|
88
|
+
# "mailer" => "1.5",
|
89
|
+
# "external-monitor-job" => "1.1",
|
90
|
+
# "ldap" => "1.2"
|
91
|
+
# }
|
92
|
+
# >> @client.plugin.list_installed(true)
|
93
|
+
# => {}
|
94
|
+
#
|
95
|
+
# @example Listing installed plugins based on filters provided
|
96
|
+
# >> @client.plugin.list_installed(
|
97
|
+
# :active => true, :deleted => false, :bundled => false
|
98
|
+
# )
|
99
|
+
# => {
|
100
|
+
# "sourcemonitor" => "0.2",
|
101
|
+
# "sms-notification" => "1.0",
|
102
|
+
# "jquery" => "1.7.2-1",
|
103
|
+
# "simple-theme-plugin" => "0.3",
|
104
|
+
# "jquery-ui" => "1.0.2",
|
105
|
+
# "analysis-core" => "1.49"
|
106
|
+
# }
|
107
|
+
#
|
108
|
+
def list_installed(filters = {})
|
109
|
+
supported_filters = [
|
110
|
+
:active, :bundled, :deleted, :downgradable, :enabled, :hasUpdate,
|
111
|
+
:pinned
|
112
|
+
]
|
113
|
+
unless filters.keys.all? { |filter| supported_filters.include?(filter) }
|
114
|
+
raise ArgumentError, "Unsupported filters specified." +
|
115
|
+
" Supported filters: #{supported_filters.inspect}"
|
116
|
+
end
|
117
|
+
tree_filters = filters.empty? ? "" : ",#{filters.keys.join(",")}"
|
118
|
+
plugins = @client.api_get_request(
|
119
|
+
"/pluginManager",
|
120
|
+
"tree=plugins[shortName,version#{tree_filters}]"
|
121
|
+
)["plugins"]
|
122
|
+
installed = Hash[plugins.map do |plugin|
|
123
|
+
if filters.keys.all? { |key| plugin[key.to_s] == filters[key] }
|
124
|
+
[plugin["shortName"], plugin["version"]]
|
125
|
+
end
|
126
|
+
end]
|
127
|
+
installed
|
128
|
+
end
|
129
|
+
|
130
|
+
# Obtains the details of a single installed plugin
|
131
|
+
#
|
132
|
+
# @param plugin [String] the plugin ID of the desired plugin
|
133
|
+
#
|
134
|
+
# @return [Hash] the details of the given installed plugin
|
135
|
+
#
|
136
|
+
# @example Obtain the information of an installed plugin
|
137
|
+
# >> @client.plugin.get_installed_info "ldap"
|
138
|
+
# => {
|
139
|
+
# "active"=>false,
|
140
|
+
# "backupVersion"=>"1.2",
|
141
|
+
# "bundled"=>true,
|
142
|
+
# "deleted"=>false,
|
143
|
+
# "dependencies"=>[],
|
144
|
+
# "downgradable"=>true,
|
145
|
+
# "enabled"=>false,
|
146
|
+
# "hasUpdate"=>false,
|
147
|
+
# "longName"=>"LDAP Plugin",
|
148
|
+
# "pinned"=>true,
|
149
|
+
# "shortName"=>"ldap",
|
150
|
+
# "supportsDynamicLoad"=>"MAYBE",
|
151
|
+
# "url"=>"http://wiki.jenkins-ci.org/display/JENKINS/LDAP+Plugin",
|
152
|
+
# "version"=>"1.5"
|
153
|
+
# }
|
154
|
+
#
|
155
|
+
def get_installed_info(plugin)
|
156
|
+
@logger.info "Obtaining the details of plugin: #{plugin}"
|
157
|
+
plugins = @client.api_get_request(
|
158
|
+
"/pluginManager",
|
159
|
+
"depth=1"
|
160
|
+
)["plugins"]
|
161
|
+
matched_plugin = plugins.select do |a_plugin|
|
162
|
+
a_plugin["shortName"] == plugin
|
163
|
+
end
|
164
|
+
if matched_plugin.empty?
|
165
|
+
raise Exceptions::PluginNotFound.new(
|
166
|
+
@logger,
|
167
|
+
"Plugin '#{plugin}' is not found"
|
168
|
+
)
|
169
|
+
else
|
170
|
+
matched_plugin.first
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# List the available plugins from jenkins update center along with their
|
175
|
+
# version numbers
|
176
|
+
#
|
177
|
+
# @param filters [Hash] optional filters to filter available plugins.
|
178
|
+
#
|
179
|
+
# @option filters [Array] :category the category of the plugin to
|
180
|
+
# filter
|
181
|
+
# @option filters [Array] :dependency the dependency of the plugin to
|
182
|
+
# filter
|
183
|
+
#
|
184
|
+
# @return [Hash<String, String>] available plugins and their versions.
|
185
|
+
# returns an empty if no plugins are available.
|
186
|
+
#
|
187
|
+
# @example Listing available plugins from jenkins
|
188
|
+
# >> @client.plugin.list_available
|
189
|
+
# => {
|
190
|
+
# "accurev" => "0.6.18",
|
191
|
+
# "active-directory" => "1.33",
|
192
|
+
# "AdaptivePlugin" => "0.1",
|
193
|
+
# ...
|
194
|
+
# "zubhium" => "0.1.6"
|
195
|
+
# }
|
196
|
+
#
|
197
|
+
# @example Listing available plugins matching a particular category
|
198
|
+
# >> pp @client.plugin.list_available(:category => "ui")
|
199
|
+
# => {
|
200
|
+
# "all-changes"=>"1.3",
|
201
|
+
# "bruceschneier"=>"0.1",
|
202
|
+
# ...
|
203
|
+
# "xfpanel"=>"1.2.2"
|
204
|
+
# }
|
205
|
+
#
|
206
|
+
# @example Listing available plugins matching a particular dependency
|
207
|
+
# >> pp @client.plugin.list_available(:dependency => "git")
|
208
|
+
# => {
|
209
|
+
# "build-failure-analyzer"=>"1.5.0",
|
210
|
+
# "buildheroes"=>"0.2",
|
211
|
+
# ...
|
212
|
+
# "xpdev"=>"1.0"
|
213
|
+
# }
|
214
|
+
#
|
215
|
+
def list_available(filters = {})
|
216
|
+
supported_filters = [:category, :dependency]
|
217
|
+
filter_plural_map = {
|
218
|
+
:dependency => "dependencies",
|
219
|
+
:category => "categories"
|
220
|
+
}
|
221
|
+
unless filters.keys.all? { |filter| supported_filters.include?(filter) }
|
222
|
+
raise ArgumentError, "Unsupported filters specified." +
|
223
|
+
" Supported filters: #{supported_filters.inspect}"
|
224
|
+
end
|
225
|
+
# Compute the filters to be passed to the JSON tree parameter
|
226
|
+
tree_filters =
|
227
|
+
if filters.empty?
|
228
|
+
""
|
229
|
+
else
|
230
|
+
",#{filters.keys.map{ |key| filter_plural_map[key] }.join(",")}"
|
231
|
+
end
|
232
|
+
|
233
|
+
availables = @client.api_get_request(
|
234
|
+
"/updateCenter/coreSource",
|
235
|
+
"tree=availables[name,version#{tree_filters}]"
|
236
|
+
)["availables"]
|
237
|
+
Hash[availables.map do |plugin|
|
238
|
+
if filters.keys.all? do |key|
|
239
|
+
!plugin[filter_plural_map[key]].nil? &&
|
240
|
+
plugin[filter_plural_map[key]].include?(filters[key])
|
241
|
+
end
|
242
|
+
[plugin["name"], plugin["version"]]
|
243
|
+
end
|
244
|
+
end]
|
245
|
+
end
|
246
|
+
|
247
|
+
# Obtains the information about a plugin that is available in the Jenkins
|
248
|
+
# update center
|
249
|
+
#
|
250
|
+
# @param plugin [String] the plugin ID to obtain information for
|
251
|
+
#
|
252
|
+
# @return [Hash] the details of the given plugin
|
253
|
+
#
|
254
|
+
# @example Obtaining the details of a plugin available in jenkins
|
255
|
+
# >> @client.plugin.get_available_info "status-view"
|
256
|
+
# => {
|
257
|
+
# "name"=>"status-view",
|
258
|
+
# "sourceId"=>"default",
|
259
|
+
# "url"=>"http://updates.jenkins-ci.org/download/plugins/status-view/1.0/status-view.hpi",
|
260
|
+
# "version"=>"1.0",
|
261
|
+
# "categories"=>["ui"],
|
262
|
+
# "compatibleSinceVersion"=>nil,
|
263
|
+
# "compatibleWithInstalledVersion"=>true,
|
264
|
+
# "dependencies"=>{},
|
265
|
+
# "excerpt"=>"View type to show jobs filtered by the status of the last completed build.",
|
266
|
+
# "installed"=>nil, "neededDependencies"=>[],
|
267
|
+
# "requiredCore"=>"1.342",
|
268
|
+
# "title"=>"Status View Plugin",
|
269
|
+
# "wiki"=>"https://wiki.jenkins-ci.org/display/JENKINS/Status+View+Plugin"
|
270
|
+
# }
|
271
|
+
#
|
272
|
+
def get_available_info(plugin)
|
273
|
+
plugins = @client.api_get_request(
|
274
|
+
"/updateCenter/coreSource",
|
275
|
+
"depth=1"
|
276
|
+
)["availables"]
|
277
|
+
matched_plugin = plugins.select do |a_plugin|
|
278
|
+
a_plugin["name"] == plugin
|
279
|
+
end
|
280
|
+
if matched_plugin.empty?
|
281
|
+
raise Exceptions::PluginNotFound.new(
|
282
|
+
@logger,
|
283
|
+
"Plugin '#{plugin}' is not found"
|
284
|
+
)
|
285
|
+
else
|
286
|
+
matched_plugin.first
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
# List the available updates for plugins from jenkins update center
|
291
|
+
# along with their version numbers
|
292
|
+
#
|
293
|
+
# @return [Hash<String, String>] available plugin updates and their
|
294
|
+
# versions. returns an empty if no plugins are available.
|
295
|
+
#
|
296
|
+
# @example Listing available plugin updates from jenkins
|
297
|
+
# >> @client.plugin.list_updates
|
298
|
+
# => {
|
299
|
+
# "ldap" => "1.5",
|
300
|
+
# "ssh-slaves" => "0.27",
|
301
|
+
# "subversion" => "1".50
|
302
|
+
# }
|
303
|
+
#
|
304
|
+
def list_updates
|
305
|
+
updates = @client.api_get_request(
|
306
|
+
"/updateCenter/coreSource",
|
307
|
+
"tree=updates[name,version]"
|
308
|
+
)["updates"]
|
309
|
+
Hash[updates.map { |plugin| [plugin["name"], plugin["version"]] }]
|
310
|
+
end
|
311
|
+
|
312
|
+
# Installs a specific plugin or list of plugins. This method will install
|
313
|
+
# the latest available plugins that jenkins reports. The installation
|
314
|
+
# might not take place right away for some plugins and they might require
|
315
|
+
# restart of jenkins instances. This method makes a single POST request
|
316
|
+
# for the installation of multiple plugins. Updating plugins can be done
|
317
|
+
# the same way. When the install action is issued, it gets the latest
|
318
|
+
# version of the plugin if the plugin is outdated.
|
319
|
+
#
|
320
|
+
# @see Client#api_post_request
|
321
|
+
# @see #restart_required?
|
322
|
+
# @see System#restart
|
323
|
+
# @see #uninstall
|
324
|
+
#
|
325
|
+
# @param plugins [String, Array] a single plugin or a list of plugins to
|
326
|
+
# be installed
|
327
|
+
#
|
328
|
+
# @return [String] the HTTP code from the plugin install POST request
|
329
|
+
#
|
330
|
+
# @example Installing a plugin and restart jenkins if required
|
331
|
+
# >> @client.plugin.install "s3"
|
332
|
+
# => "302" # Response code from plugin installation POST
|
333
|
+
# >> @client.plugin.restart_required?
|
334
|
+
# => true # A restart is required for the installation completion
|
335
|
+
# >> @client.system.restart(true)
|
336
|
+
# => "302" # A force restart is performed
|
337
|
+
#
|
338
|
+
def install(plugins)
|
339
|
+
# Convert the input argument to an array if it is not already an array
|
340
|
+
plugins = [plugins] unless plugins.is_a?(Array)
|
341
|
+
@logger.info "Installing plugins: #{plugins.inspect}"
|
342
|
+
|
343
|
+
# Build the form data to post to jenkins
|
344
|
+
form_data = {}
|
345
|
+
plugins.each { |plugin| form_data["plugin.#{plugin}.default"] = "on" }
|
346
|
+
@client.api_post_request("/pluginManager/install", form_data)
|
347
|
+
end
|
348
|
+
alias_method :update, :install
|
349
|
+
|
350
|
+
|
351
|
+
# @!method uninstall(plugins)
|
352
|
+
#
|
353
|
+
# Uninstalls the specified plugin or list of plugins. Only the user
|
354
|
+
# installed plugins can be uninstalled. The plugins installed by default
|
355
|
+
# by jenkins (also known as bundled plugins) cannot be uninstalled. The
|
356
|
+
# call will succeed but the plugins wil still remain in jenkins installed.
|
357
|
+
# This method makes a POST request for every plugin requested - so it
|
358
|
+
# might lead to some delay if a big list is provided.
|
359
|
+
#
|
360
|
+
# @see Client#api_post_request
|
361
|
+
# @see #restart_required?
|
362
|
+
# @see System#restart
|
363
|
+
# @see #install
|
364
|
+
#
|
365
|
+
# @param plugins [String, Array] a single plugin or list of plugins to be
|
366
|
+
# uninstalled
|
367
|
+
#
|
368
|
+
plugin_action_method :uninstall, :doUninstall
|
369
|
+
|
370
|
+
# @!method downgrade(plugins)
|
371
|
+
#
|
372
|
+
# Downgrades the specified plugin or list of plugins. This method makes s
|
373
|
+
# POST request for every plugin specified - so it might lead to some
|
374
|
+
# delay if a big list is provided.
|
375
|
+
#
|
376
|
+
# @see Client#api_post_request
|
377
|
+
# @see #restart_required?
|
378
|
+
# @see System#restart
|
379
|
+
# @see #install
|
380
|
+
#
|
381
|
+
# @param [String, Array] a single plugin or list of plugins to be
|
382
|
+
# downgraded
|
383
|
+
#
|
384
|
+
plugin_action_method :downgrade, :downgrade
|
385
|
+
|
386
|
+
# @!method unpin(plugins)
|
387
|
+
#
|
388
|
+
# Unpins the specified plugin or list of plugins. This method makes a
|
389
|
+
# POST request for every plugin specified - so it might lead to some
|
390
|
+
# delay if a big list is provided.
|
391
|
+
#
|
392
|
+
# @see Client#api_post_request
|
393
|
+
# @see #restart_required?
|
394
|
+
# @see System#restart
|
395
|
+
#
|
396
|
+
# @param plugins [String, Array] a single plugin or list of plugins to be
|
397
|
+
# uninstalled
|
398
|
+
#
|
399
|
+
plugin_action_method :unpin, :unpin
|
400
|
+
|
401
|
+
# @!method enable(plugins)
|
402
|
+
#
|
403
|
+
# Enables the specified plugin or list of plugins. This method makes a
|
404
|
+
# POST request for every plugin specified - so it might lead to some
|
405
|
+
# delay if a big list is provided.
|
406
|
+
#
|
407
|
+
# @see Client#api_post_request
|
408
|
+
# @see #restart_required?
|
409
|
+
# @see System#restart
|
410
|
+
# @see #disable
|
411
|
+
#
|
412
|
+
# @param plugins [String, Array] a single plugin or list of plugins to be
|
413
|
+
# uninstalled
|
414
|
+
#
|
415
|
+
plugin_action_method :enable, :makeEnabled
|
416
|
+
|
417
|
+
# @!method disable(plugins)
|
418
|
+
#
|
419
|
+
# Disables the specified plugin or list of plugins. This method makes a
|
420
|
+
# POST request for every plugin specified - so it might lead to some
|
421
|
+
# delay if a big list is provided.
|
422
|
+
#
|
423
|
+
# @see Client#api_post_request
|
424
|
+
# @see #restart_required?
|
425
|
+
# @see System#restart
|
426
|
+
# @see #enable
|
427
|
+
#
|
428
|
+
# @param plugins [String, Array] a single plugin or list of plugins to be
|
429
|
+
# uninstalled
|
430
|
+
#
|
431
|
+
plugin_action_method :disable, :makeDisabled
|
432
|
+
|
433
|
+
# Requests the Jenkins plugin manager to check for updates by connecting
|
434
|
+
# to the update site.
|
435
|
+
#
|
436
|
+
# @see #list_updates
|
437
|
+
#
|
438
|
+
def check_for_updates
|
439
|
+
@client.api_post_request("/pluginManager/checkUpdates")
|
440
|
+
end
|
441
|
+
|
442
|
+
# Whether restart required for the completion of plugin
|
443
|
+
# installations/uninstallations
|
444
|
+
#
|
445
|
+
# @see Client#api_get_request
|
446
|
+
#
|
447
|
+
# @return [Boolean] whether restart is required for the completion for
|
448
|
+
# plugin installations/uninstallations.
|
449
|
+
#
|
450
|
+
def restart_required?
|
451
|
+
response = @client.api_get_request(
|
452
|
+
"/updateCenter",
|
453
|
+
"tree=restartRequiredForCompletion"
|
454
|
+
)
|
455
|
+
response["restartRequiredForCompletion"] ||
|
456
|
+
!list_installed(:deleted => true).empty?
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|