improved_jenkins_client 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|