improved_jenkins_client 1.6.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 +7 -0
- data/bin/jenkinscli +5 -0
- data/improved_jenkins_client.gemspec +34 -0
- data/java_deps/jenkins-cli.jar +0 -0
- data/lib/improved_jenkins_client/build_queue.rb +262 -0
- data/lib/improved_jenkins_client/cli/base.rb +84 -0
- data/lib/improved_jenkins_client/cli/helper.rb +61 -0
- data/lib/improved_jenkins_client/cli/job.rb +133 -0
- data/lib/improved_jenkins_client/cli/node.rb +97 -0
- data/lib/improved_jenkins_client/cli/system.rb +65 -0
- data/lib/improved_jenkins_client/client.rb +855 -0
- data/lib/improved_jenkins_client/exceptions.rb +246 -0
- data/lib/improved_jenkins_client/job.rb +1966 -0
- data/lib/improved_jenkins_client/node.rb +353 -0
- data/lib/improved_jenkins_client/plugin_manager.rb +460 -0
- data/lib/improved_jenkins_client/plugin_settings/base.rb +11 -0
- data/lib/improved_jenkins_client/plugin_settings/collection.rb +39 -0
- data/lib/improved_jenkins_client/plugin_settings/hipchat.rb +53 -0
- data/lib/improved_jenkins_client/plugin_settings/workspace_cleanup.rb +35 -0
- data/lib/improved_jenkins_client/root.rb +67 -0
- data/lib/improved_jenkins_client/system.rb +134 -0
- data/lib/improved_jenkins_client/urihelper.rb +18 -0
- data/lib/improved_jenkins_client/user.rb +131 -0
- data/lib/improved_jenkins_client/version.rb +36 -0
- data/lib/improved_jenkins_client/view.rb +313 -0
- data/lib/improved_jenkins_client.rb +52 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 19904a21383083aac042b3519246181d77b42a0dd70a9d24681c3f1b1f4107eb
|
4
|
+
data.tar.gz: 59edb7776fff8d492802d16cbc098af2b7caf6143c98f9126a480050fc5aa510
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 612ea06785632e4b6392bcd2b8ee6250945f3baa59f96cae4c08fe1b28dbc4d5169ab25a3fb645d857cbac1e59e8561e6617b32625aea626ab505d7a87ce8aa9
|
7
|
+
data.tar.gz: 7f60050161fb200ef85ecb5d6304830dd6c9f7b339ee4fc16a727b1bcdab75efe4474cdce6181e8bc3d89428c663e77c88fd7acb6247ea53e29f91dc2ca6db20
|
data/bin/jenkinscli
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'improved_jenkins_client/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "improved_jenkins_client"
|
7
|
+
s.version = ::JenkinsApi::Client::VERSION
|
8
|
+
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
|
+
s.require_paths = ["lib"]
|
11
|
+
s.authors = ["Kannan Manickam", "Yugabyte engineering team"]
|
12
|
+
s.description =
|
13
|
+
"\nThis is a simple and easy-to-use Jenkins Api client with features focused on" +
|
14
|
+
"\nautomating Job configuration programaticaly. Based on the improved_jenkins_client with" +
|
15
|
+
"\nimprovements by Yugabyte engineering team."
|
16
|
+
|
17
|
+
s.email = ["yugabyte-ci@users.noreply.github.com"]
|
18
|
+
s.executables = ['jenkinscli']
|
19
|
+
s.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r{lib/|bin/|java_deps/|gemspec}) }
|
20
|
+
s.require_paths = ['lib']
|
21
|
+
s.homepage = 'https://github.com/yugabyte-db/improved-ruby-jenkins-client'
|
22
|
+
s.required_ruby_version = ::Gem::Requirement.new('~> 2.1')
|
23
|
+
s.rubygems_version = "2.4.5.1"
|
24
|
+
s.summary = "Improved Jenkins JSON API Client"
|
25
|
+
s.licenses = ["MIT"]
|
26
|
+
|
27
|
+
s.add_dependency 'nokogiri', '~> 1.6'
|
28
|
+
s.add_dependency 'thor', '>= 0.16.0'
|
29
|
+
s.add_dependency 'terminal-table', '>= 1.4.0'
|
30
|
+
s.add_dependency 'mixlib-shellout', '>= 1.1.0'
|
31
|
+
s.add_dependency 'socksify', '>= 1.7.0'
|
32
|
+
s.add_dependency 'json', '>= 1.0'
|
33
|
+
s.add_dependency 'addressable', '~> 2.7'
|
34
|
+
end
|
Binary file
|
@@ -0,0 +1,262 @@
|
|
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 Build Queue API exposed by Jenkins at
|
26
|
+
# "/queue" that gives information about jobs/tasks in the queue and their
|
27
|
+
# details.
|
28
|
+
#
|
29
|
+
class BuildQueue
|
30
|
+
|
31
|
+
# Initializes a new BuildQueue object.
|
32
|
+
#
|
33
|
+
# @param client [Client] the client object
|
34
|
+
#
|
35
|
+
# @return [BuildQueue] the build queue object
|
36
|
+
#
|
37
|
+
def initialize(client)
|
38
|
+
@client = client
|
39
|
+
@logger = @client.logger
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a string representation of BuildQueue class.
|
43
|
+
#
|
44
|
+
def to_s
|
45
|
+
"#<JenkinsApi::Client::BuildQueue>"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Gives the number of jobs currently in the build queue
|
49
|
+
#
|
50
|
+
def size
|
51
|
+
@logger.info "Obtaining the number of tasks in build queue"
|
52
|
+
response_json = @client.api_get_request("/queue")
|
53
|
+
response_json["items"].size
|
54
|
+
end
|
55
|
+
|
56
|
+
# Lists all tasks currently in the build queue
|
57
|
+
#
|
58
|
+
def list
|
59
|
+
@logger.info "Obtaining the tasks currently in the build queue"
|
60
|
+
response_json = @client.api_get_request("/queue")
|
61
|
+
tasks = []
|
62
|
+
response_json["items"].each do |item|
|
63
|
+
tasks << item["task"]["name"]
|
64
|
+
end
|
65
|
+
tasks
|
66
|
+
end
|
67
|
+
|
68
|
+
# Gets the time number of seconds the task is in the queue
|
69
|
+
#
|
70
|
+
# @param [String] task_name Name of the task/job
|
71
|
+
#
|
72
|
+
# @return [Fixnum] age in seconds
|
73
|
+
#
|
74
|
+
def get_age(task_name)
|
75
|
+
@logger.info "Obtaining the age of task '#{task_name}' from the" +
|
76
|
+
" build queue"
|
77
|
+
age = nil
|
78
|
+
details = get_details(task_name)
|
79
|
+
unless details.empty?
|
80
|
+
age = Time.now - Time.at(details["inQueueSince"].to_i/1000)
|
81
|
+
end
|
82
|
+
age
|
83
|
+
end
|
84
|
+
|
85
|
+
# Obtains the detail Hash from the API response
|
86
|
+
#
|
87
|
+
# @param [String] task_name Name of the task/job
|
88
|
+
#
|
89
|
+
# @return [Hash] Queue details of the specified task/job
|
90
|
+
#
|
91
|
+
def get_details(task_name)
|
92
|
+
@logger.info "Obtaining the details of task '#{task_name}' from the" +
|
93
|
+
" build queue"
|
94
|
+
response_json = @client.api_get_request("/queue")
|
95
|
+
details = {}
|
96
|
+
response_json["items"].each do |item|
|
97
|
+
details = item if item["task"]["name"] == task_name
|
98
|
+
end
|
99
|
+
details
|
100
|
+
end
|
101
|
+
|
102
|
+
# Obtain the item in the queue provided the ID of the task
|
103
|
+
#
|
104
|
+
# @param task_id [String] the ID of the task
|
105
|
+
#
|
106
|
+
# @return [Hash] the details of the item in the queue
|
107
|
+
#
|
108
|
+
def get_item_by_id(task_id)
|
109
|
+
@logger.info "Obtaining the details of task with ID '#{task_id}'"
|
110
|
+
@client.api_get_request("/queue/item/#{task_id}")
|
111
|
+
end
|
112
|
+
|
113
|
+
# Obtains the causes from the build queue for the specified task
|
114
|
+
#
|
115
|
+
# @param [String] task_name
|
116
|
+
#
|
117
|
+
# @return [Array] causes for the task to be in queue
|
118
|
+
#
|
119
|
+
def get_causes(task_name)
|
120
|
+
@logger.info "Obtaining the causes of task '#{task_name}' from the" +
|
121
|
+
" build queue"
|
122
|
+
causes = nil
|
123
|
+
details = get_details(task_name)
|
124
|
+
unless details.empty?
|
125
|
+
causes = []
|
126
|
+
details["actions"].each do |action|
|
127
|
+
causes << action["causes"]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
causes
|
131
|
+
end
|
132
|
+
|
133
|
+
# Obtains the reason why the task is in queue
|
134
|
+
#
|
135
|
+
# @param [String] task_name name of the task
|
136
|
+
#
|
137
|
+
# @return [String] reason for being in queue, nil if no task found
|
138
|
+
#
|
139
|
+
def get_reason(task_name)
|
140
|
+
@logger.info "Obtaining the reason of task '#{task_name}' from the" +
|
141
|
+
" build queue"
|
142
|
+
reason = nil
|
143
|
+
details = get_details(task_name)
|
144
|
+
unless details.empty?
|
145
|
+
reason = details["why"]
|
146
|
+
end
|
147
|
+
reason
|
148
|
+
end
|
149
|
+
|
150
|
+
# Obtains the ETA given by Jenkins if any
|
151
|
+
#
|
152
|
+
# @param [String] task_name name of the task
|
153
|
+
#
|
154
|
+
# @return [String] ETA for the task, nil if no task found and N/A for
|
155
|
+
# tasks with no ETA info.
|
156
|
+
#
|
157
|
+
def get_eta(task_name)
|
158
|
+
@logger.info "Obtaining the ETA for the task '#{task_name}' from the" +
|
159
|
+
" build queue"
|
160
|
+
eta = nil
|
161
|
+
details = get_details(task_name)
|
162
|
+
unless details.empty?
|
163
|
+
matched = details["why"].match(/.*\(ETA:(.*)\)/)
|
164
|
+
if matched.nil?
|
165
|
+
# Task is found, but ETA information is not available
|
166
|
+
eta = "N/A"
|
167
|
+
else
|
168
|
+
# ETA information is available
|
169
|
+
eta = matched[1].strip
|
170
|
+
end
|
171
|
+
end
|
172
|
+
eta
|
173
|
+
end
|
174
|
+
|
175
|
+
# Obtains the ID of the task from the queue
|
176
|
+
#
|
177
|
+
# @param [String] task_name name of the task
|
178
|
+
#
|
179
|
+
# @return [String] ID of the task, nil of no task is found
|
180
|
+
#
|
181
|
+
def get_id(task_name)
|
182
|
+
@logger.info "Obtaining the ID of task '#{task_name}' from the" +
|
183
|
+
" build queue"
|
184
|
+
id = nil
|
185
|
+
details = get_details(task_name)
|
186
|
+
unless details.empty?
|
187
|
+
id = details["id"]
|
188
|
+
end
|
189
|
+
id
|
190
|
+
end
|
191
|
+
|
192
|
+
# Obtains the params from the build queue
|
193
|
+
#
|
194
|
+
# @param [String] task_name name of the task
|
195
|
+
#
|
196
|
+
# @return [String] params, nil if the no task is found
|
197
|
+
#
|
198
|
+
def get_params(task_name)
|
199
|
+
@logger.info "Obtaining the build parameters of task '#{task_name}'" +
|
200
|
+
" from the build queue"
|
201
|
+
params = nil
|
202
|
+
details = get_details(task_name)
|
203
|
+
unless details.empty?
|
204
|
+
params = details["params"]
|
205
|
+
end
|
206
|
+
params
|
207
|
+
end
|
208
|
+
|
209
|
+
# Obtains whether the task is buildable
|
210
|
+
#
|
211
|
+
# @param [String] task_name name of the task
|
212
|
+
#
|
213
|
+
# @return [Boolean] buildable or not
|
214
|
+
#
|
215
|
+
def is_buildable?(task_name)
|
216
|
+
@logger.info "Checking if task '#{task_name}' from the build queue" +
|
217
|
+
" is buildable"
|
218
|
+
buildable = nil
|
219
|
+
details = get_details(task_name)
|
220
|
+
unless details.empty?
|
221
|
+
buildable = details["buildable"]
|
222
|
+
end
|
223
|
+
buildable
|
224
|
+
end
|
225
|
+
|
226
|
+
# Obtains whether the task is blocked
|
227
|
+
#
|
228
|
+
# @param [String] task_name name of the task
|
229
|
+
#
|
230
|
+
# @return [Boolean] blocked or not
|
231
|
+
#
|
232
|
+
def is_blocked?(task_name)
|
233
|
+
@logger.info "Checking if task '#{task_name}' from the build queue" +
|
234
|
+
" is blocked"
|
235
|
+
blocked = nil
|
236
|
+
details = get_details(task_name)
|
237
|
+
unless details.empty?
|
238
|
+
blocked = details["blocked"]
|
239
|
+
end
|
240
|
+
blocked
|
241
|
+
end
|
242
|
+
|
243
|
+
# Obtains whether the task is stuck
|
244
|
+
#
|
245
|
+
# @param [String] task_name name of the task
|
246
|
+
#
|
247
|
+
# @return [Boolean] stuck or not
|
248
|
+
#
|
249
|
+
def is_stuck?(task_name)
|
250
|
+
@logger.info "Checking if task '#{task_name}' from the build queue" +
|
251
|
+
" is stuck"
|
252
|
+
stuck = nil
|
253
|
+
details = get_details(task_name)
|
254
|
+
unless details.empty?
|
255
|
+
stuck = details["stuck"]
|
256
|
+
end
|
257
|
+
stuck
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
@@ -0,0 +1,84 @@
|
|
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
|
+
require 'thor'
|
24
|
+
require 'thor/group'
|
25
|
+
require "#{File.dirname(__FILE__)}/node.rb"
|
26
|
+
require "#{File.dirname(__FILE__)}/job.rb"
|
27
|
+
require "#{File.dirname(__FILE__)}/system.rb"
|
28
|
+
|
29
|
+
module JenkinsApi
|
30
|
+
# This is the base module for all command line interface for Jenkins API.
|
31
|
+
#
|
32
|
+
module CLI
|
33
|
+
# This is the base class for the command line interface which adds other
|
34
|
+
# classes as subcommands to the CLI.
|
35
|
+
#
|
36
|
+
class Base < Thor
|
37
|
+
|
38
|
+
class_option :username, :aliases => "-u", :desc => "Name of Jenkins user"
|
39
|
+
class_option :password, :aliases => "-p",
|
40
|
+
:desc => "Password of Jenkins user"
|
41
|
+
class_option :password_base64, :aliases => "-b",
|
42
|
+
:desc => "Base 64 encoded password of Jenkins user"
|
43
|
+
class_option :server_ip, :aliases => "-s",
|
44
|
+
:desc => "Jenkins server IP address"
|
45
|
+
class_option :server_port, :aliases => "-o", :desc => "Jenkins port"
|
46
|
+
class_option :creds_file, :aliases => "-c",
|
47
|
+
:desc => "Credentials file for communicating with Jenkins server"
|
48
|
+
|
49
|
+
|
50
|
+
map "-v" => :version
|
51
|
+
|
52
|
+
desc "version", "Shows current version"
|
53
|
+
# CLI command that returns the version of Jenkins API Client
|
54
|
+
def version
|
55
|
+
puts JenkinsApi::Client::VERSION
|
56
|
+
end
|
57
|
+
|
58
|
+
# Register the CLI::Node class as "node" subcommand to CLI
|
59
|
+
register(
|
60
|
+
CLI::Node,
|
61
|
+
'node',
|
62
|
+
'node [subcommand]',
|
63
|
+
'Provides functions to access the node interface of Jenkins CI server'
|
64
|
+
)
|
65
|
+
|
66
|
+
# Register the CLI::Job class as "job" subcommand to CLI
|
67
|
+
register(
|
68
|
+
CLI::Job,
|
69
|
+
'job',
|
70
|
+
'job [subcommand]',
|
71
|
+
'Provides functions to access the job interface of Jenkins CI server'
|
72
|
+
)
|
73
|
+
|
74
|
+
# Register the CLI::System class as "system" subcommand to CLI
|
75
|
+
register(
|
76
|
+
CLI::System,
|
77
|
+
'system',
|
78
|
+
'system [subcommand]',
|
79
|
+
'Provides functions to access system functions of the Jenkins CI server'
|
80
|
+
)
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,61 @@
|
|
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
|
+
require 'fileutils'
|
24
|
+
require 'yaml'
|
25
|
+
|
26
|
+
module JenkinsApi
|
27
|
+
module CLI
|
28
|
+
# This is the helper class that sets up the credentials from the command
|
29
|
+
# line parameters given and initializes the Jenkins API Client.
|
30
|
+
class Helper
|
31
|
+
# Sets up the credentials and initializes the Jenkins API Client
|
32
|
+
#
|
33
|
+
# @param [Hash] options Options obtained from the command line
|
34
|
+
#
|
35
|
+
# @return [JenkinsApi::Client] A new Client object
|
36
|
+
#
|
37
|
+
def self.setup(options)
|
38
|
+
if options[:username] && options[:server_ip] && \
|
39
|
+
(options[:password] || options[:password_base64])
|
40
|
+
creds = options
|
41
|
+
elsif options[:creds_file]
|
42
|
+
creds = YAML.load_file(
|
43
|
+
File.expand_path(options[:creds_file], __FILE__)
|
44
|
+
)
|
45
|
+
elsif File.exist?("#{ENV['HOME']}/.improved_jenkins_client/login.yml")
|
46
|
+
creds = YAML.load_file(
|
47
|
+
File.expand_path(
|
48
|
+
"#{ENV['HOME']}/.improved_jenkins_client/login.yml", __FILE__
|
49
|
+
)
|
50
|
+
)
|
51
|
+
else
|
52
|
+
msg = "Credentials are not set. Please pass them as parameters or"
|
53
|
+
msg << " set them in the default credentials file"
|
54
|
+
puts msg
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
JenkinsApi::Client.new(creds)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,133 @@
|
|
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
|
+
require 'thor'
|
24
|
+
require 'thor/group'
|
25
|
+
|
26
|
+
module JenkinsApi
|
27
|
+
module CLI
|
28
|
+
# This class provides various command line operations related to jobs.
|
29
|
+
class Job < Thor
|
30
|
+
include Thor::Actions
|
31
|
+
|
32
|
+
desc "list", "List jobs"
|
33
|
+
method_option :status, :aliases => "-t", :desc => "Status to filter"
|
34
|
+
method_option :filter, :aliases => "-f",
|
35
|
+
:desc => "Regular expression to filter jobs"
|
36
|
+
# CLI command to list all jobs in Jenkins or the ones matched by status
|
37
|
+
# or a regular expression
|
38
|
+
def list
|
39
|
+
@client = Helper.setup(parent_options)
|
40
|
+
if options[:filter] && options[:status]
|
41
|
+
name_filtered = @client.job.list(options[:filter])
|
42
|
+
puts @client.job.list_by_status(options[:status], name_filtered)
|
43
|
+
elsif options[:filter]
|
44
|
+
puts @client.job.list(options[:filter])
|
45
|
+
elsif options[:status]
|
46
|
+
puts @client.job.list_by_status(options[:status])
|
47
|
+
else
|
48
|
+
puts @client.job.list_all
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "recreate JOB", "Recreate a specified job"
|
53
|
+
# CLI command to recreate a job on Jenkins
|
54
|
+
def recreate(job)
|
55
|
+
@client = Helper.setup(parent_options)
|
56
|
+
@client.job.recreate(job)
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "build JOB", "Build a job"
|
60
|
+
# CLI command to build a job given the name of the job
|
61
|
+
#
|
62
|
+
# @param [String] job Name of the job
|
63
|
+
#
|
64
|
+
option :params, :type => :hash, :default => {}
|
65
|
+
option :opts, :type => :hash, :default => {}
|
66
|
+
def build(job)
|
67
|
+
@client = Helper.setup(parent_options)
|
68
|
+
@client.job.build(job, options[:params], options[:opts])
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "status JOB", "Get the current build status of a job"
|
72
|
+
# CLI command to get the status of a job
|
73
|
+
#
|
74
|
+
# @param [String] job Name of the job
|
75
|
+
#
|
76
|
+
def status(job)
|
77
|
+
@client = Helper.setup(parent_options)
|
78
|
+
puts @client.job.get_current_build_status(job)
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "delete JOB", "Delete the job"
|
82
|
+
# CLI command to delete a job
|
83
|
+
#
|
84
|
+
# @param [String] job Name of the job
|
85
|
+
#
|
86
|
+
def delete(job)
|
87
|
+
@client = Helper.setup(parent_options)
|
88
|
+
puts @client.job.delete(job)
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "console JOB", "Print the progressive console output of a job"
|
92
|
+
method_option :sleep, :aliases => "-z",
|
93
|
+
:desc => "Time to wait between querying the API for console output"
|
94
|
+
# CLI command to obtain console output for a job. Make sure the log
|
95
|
+
# location is set to something other than STDOUT. By default it is set to
|
96
|
+
# STDOUT. If the log messages are printed on the same console, the
|
97
|
+
# console output will get garbled.
|
98
|
+
#
|
99
|
+
# @param [String] job Name of the job
|
100
|
+
#
|
101
|
+
def console(job)
|
102
|
+
@client = Helper.setup(parent_options)
|
103
|
+
# Print progressive console output
|
104
|
+
response = @client.job.get_console_output(job)
|
105
|
+
puts response['output'] unless response['more']
|
106
|
+
while response['more']
|
107
|
+
size = response['size']
|
108
|
+
puts response['output'] unless response['output'].chomp.empty?
|
109
|
+
sleep options[:sleep].to_i if options[:sleep]
|
110
|
+
response = @client.job.get_console_output(job, 0, size)
|
111
|
+
end
|
112
|
+
# Print the last few lines
|
113
|
+
puts response['output'] unless response['output'].chomp.empty?
|
114
|
+
end
|
115
|
+
|
116
|
+
desc "restrict JOB", "Restricts a job to a specific node"
|
117
|
+
method_option :node, :aliases => "-n", :desc => "Node to be restricted to"
|
118
|
+
# CLI command to restrict a job to a node
|
119
|
+
#
|
120
|
+
# @param [String] job Name of the job
|
121
|
+
#
|
122
|
+
def restrict(job)
|
123
|
+
@client = Helper.setup(parent_options)
|
124
|
+
if options[:node]
|
125
|
+
@client.job.restrict_to_node(job, options[:node])
|
126
|
+
else
|
127
|
+
say "You need to specify the node to be restricted to.", :red
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,97 @@
|
|
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
|
+
require 'thor'
|
24
|
+
require 'thor/group'
|
25
|
+
require 'terminal-table'
|
26
|
+
|
27
|
+
module JenkinsApi
|
28
|
+
module CLI
|
29
|
+
# This class provides various command line operations for the Node class.
|
30
|
+
class Node < Thor
|
31
|
+
include Thor::Actions
|
32
|
+
include Terminal
|
33
|
+
|
34
|
+
desc "list", "List all nodes"
|
35
|
+
method_option :filter, :aliases => "-f",
|
36
|
+
:desc => "Regular expression to filter jobs"
|
37
|
+
# CLI command that lists all nodes/slaves available in Jenkins or the
|
38
|
+
# ones matching the filter provided
|
39
|
+
def list
|
40
|
+
@client = Helper.setup(parent_options)
|
41
|
+
if options[:filter]
|
42
|
+
puts @client.node.list(options[:filter])
|
43
|
+
else
|
44
|
+
puts @client.node.list
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "print_general_attributes", "Prints general attributes of nodes"
|
49
|
+
# CLI command that prints the general attribtues of nodes
|
50
|
+
def print_general_attributes
|
51
|
+
@client = Helper.setup(parent_options)
|
52
|
+
general_attributes = Client::Node::GENERAL_ATTRIBUTES
|
53
|
+
rows = []
|
54
|
+
general_attributes.each do |attr|
|
55
|
+
rows << [attr, @client.node.method("get_#{attr}").call]
|
56
|
+
end
|
57
|
+
table = Table.new :headings => ['Attribute', 'Value'], :rows => rows
|
58
|
+
puts table
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "print_node_attributes NODE", "Prints attributes specific to a node"
|
62
|
+
# CLI command to print the attributes specific to a node
|
63
|
+
#
|
64
|
+
# @param [String] node Name of the node
|
65
|
+
#
|
66
|
+
def print_node_attributes(node)
|
67
|
+
@client = Helper.setup(parent_options)
|
68
|
+
node_attributes = Client::Node::NODE_ATTRIBUTES
|
69
|
+
rows = []
|
70
|
+
node_attributes.each do |attr|
|
71
|
+
rows << [attr, @client.node.method("get_node_#{attr}").call(node)]
|
72
|
+
end
|
73
|
+
table = Table.new :headings => ['Attribute', 'Value'], :rows => rows
|
74
|
+
puts "Node: #{node}"
|
75
|
+
puts table
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "print_node_properties NODE", "Prints properties of a node"
|
79
|
+
# CLI command to print the properties of a specific node
|
80
|
+
#
|
81
|
+
# @param [String] node Name of the node
|
82
|
+
#
|
83
|
+
def print_node_properties(node)
|
84
|
+
@client = Helper.setup(parent_options)
|
85
|
+
node_properties = Client::Node::NODE_PROPERTIES
|
86
|
+
rows = []
|
87
|
+
node_properties.each do |property|
|
88
|
+
rows << [property, @client.node.method("is_#{property}?").call(node)]
|
89
|
+
end
|
90
|
+
table = Table.new :headings => ['Property', 'Value'], :rows => rows
|
91
|
+
puts "Node: #{node}"
|
92
|
+
puts table
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|