jenkins_api_client 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +23 -0
- data/CHANGELOG.rdoc +7 -1
- data/Gemfile +5 -3
- data/{README.rdoc → README.md} +69 -46
- data/lib/jenkins_api_client/cli/base.rb +33 -9
- data/lib/jenkins_api_client/cli/helper.rb +43 -0
- data/lib/jenkins_api_client/cli/job.rb +8 -37
- data/lib/jenkins_api_client/cli/node.rb +83 -0
- data/lib/jenkins_api_client/cli/system.rb +53 -0
- data/lib/jenkins_api_client/client.rb +35 -1
- data/lib/jenkins_api_client/job.rb +32 -16
- data/lib/jenkins_api_client/node.rb +149 -0
- data/lib/jenkins_api_client/system.rb +87 -0
- data/lib/jenkins_api_client/version.rb +5 -1
- data/spec/client_spec.rb +5 -0
- data/spec/node_spec.rb +48 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/system_spec.rb +46 -0
- metadata +54 -15
@@ -0,0 +1,83 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 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
|
+
class Node < Thor
|
30
|
+
include Thor::Actions
|
31
|
+
|
32
|
+
desc "list", "List all nodes"
|
33
|
+
method_option :filter, :aliases => "-f", :desc => "Regular expression to filter jobs"
|
34
|
+
def list
|
35
|
+
@client = Helper.setup(parent_options)
|
36
|
+
if options[:filter]
|
37
|
+
puts @client.node.list(options[:filter])
|
38
|
+
else
|
39
|
+
puts @client.node.list
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "print_general_attributes", "Prints general attributes of nodes"
|
44
|
+
def print_general_attributes
|
45
|
+
@client = Helper.setup(parent_options)
|
46
|
+
general_attributes = Client::Node::GENERAL_ATTRIBUTES
|
47
|
+
rows = []
|
48
|
+
general_attributes.each do |attr|
|
49
|
+
rows << [attr, @client.node.method("get_#{attr}").call]
|
50
|
+
end
|
51
|
+
table = Terminal::Table.new :headings => ['Attribute', 'Value'], :rows => rows
|
52
|
+
puts table
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "print_node_attributes NODE", "Prints attributes specific to a node"
|
56
|
+
def print_node_attributes(node)
|
57
|
+
@client = Helper.setup(parent_options)
|
58
|
+
node_attributes = Client::Node::NODE_ATTRIBUTES
|
59
|
+
rows = []
|
60
|
+
node_attributes.each do |attr|
|
61
|
+
rows << [attr, @client.node.method("get_node_#{attr}").call(node)]
|
62
|
+
end
|
63
|
+
table = Terminal::Table.new :headings => ['Attribute', 'Value'], :rows => rows
|
64
|
+
puts "Node: #{node}"
|
65
|
+
puts table
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "print_node_properties NODE", "Prints properties of a node"
|
69
|
+
def print_node_properties(node)
|
70
|
+
@client = Helper.setup(parent_options)
|
71
|
+
node_properties = Client::Node::NODE_PROPERTIES
|
72
|
+
rows = []
|
73
|
+
node_properties.each do |property|
|
74
|
+
rows << [property, @client.node.method("is_#{property}?").call(node)]
|
75
|
+
end
|
76
|
+
table = Terminal::Table.new :headings => ['Property', 'Value'], :rows => rows
|
77
|
+
puts "Node: #{node}"
|
78
|
+
puts table
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 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
|
+
class System < Thor
|
29
|
+
include Thor::Actions
|
30
|
+
|
31
|
+
desc "quietdown", "Puts the Jenkins server in Quiet down mode"
|
32
|
+
def quietdown
|
33
|
+
@client = Helper.setup(parent_options)
|
34
|
+
@client.system.quiet_down
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "cancel_quietdown", "Cancels the Quiet down mode of Jenkins server"
|
38
|
+
def cancel_quietdown
|
39
|
+
@client = Helper.setup(parent_options)
|
40
|
+
@client.system.cancel_quiet_down
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "restart", "Restarts the Jenkins server"
|
44
|
+
method_option :force, :type => :boolean, :aliases => "-s", :desc => "Force restart"
|
45
|
+
def restart
|
46
|
+
@client = Helper.setup(parent_options)
|
47
|
+
force = options[:force] ? true : false
|
48
|
+
@client.system.restart(force)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -31,6 +31,8 @@ require 'base64'
|
|
31
31
|
require File.expand_path('../version', __FILE__)
|
32
32
|
require File.expand_path('../exceptions', __FILE__)
|
33
33
|
require File.expand_path('../job', __FILE__)
|
34
|
+
require File.expand_path('../system', __FILE__)
|
35
|
+
require File.expand_path('../node', __FILE__)
|
34
36
|
|
35
37
|
module JenkinsApi
|
36
38
|
class Client
|
@@ -61,18 +63,45 @@ module JenkinsApi
|
|
61
63
|
@password = Base64.decode64(@password_base64).chomp if @password_base64
|
62
64
|
end
|
63
65
|
|
64
|
-
#
|
66
|
+
# This method toggles the debug parameter in run time
|
67
|
+
#
|
68
|
+
def toggle_debug
|
69
|
+
@debug = @debug == false ? true : false
|
70
|
+
end
|
71
|
+
|
72
|
+
# Creates an instance to the Job class by passing a reference to self
|
65
73
|
#
|
66
74
|
def job
|
67
75
|
JenkinsApi::Client::Job.new(self)
|
68
76
|
end
|
69
77
|
|
78
|
+
# Creates an instance to the System class by passing a reference to self
|
79
|
+
#
|
80
|
+
def system
|
81
|
+
JenkinsApi::Client::System.new(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Creates an instance to the Node class by passing a reference to self
|
85
|
+
#
|
86
|
+
def node
|
87
|
+
JenkinsApi::Client::Node.new(self)
|
88
|
+
end
|
89
|
+
|
70
90
|
# Returns a string representing the class name
|
71
91
|
#
|
72
92
|
def to_s
|
73
93
|
"#<JenkinsApi::Client>"
|
74
94
|
end
|
75
95
|
|
96
|
+
# Obtains the root of Jenkins server. This function is used to see if
|
97
|
+
# Jenkins is running
|
98
|
+
def get_root
|
99
|
+
http = Net::HTTP.start(@server_ip, @server_port)
|
100
|
+
request = Net::HTTP::Get.new("/")
|
101
|
+
request.basic_auth @username, @password
|
102
|
+
http.request(request)
|
103
|
+
end
|
104
|
+
|
76
105
|
# Sends a GET request to the Jenkins CI server with the specified URL
|
77
106
|
#
|
78
107
|
# @param [String] url_prefix
|
@@ -80,6 +109,8 @@ module JenkinsApi
|
|
80
109
|
def api_get_request(url_prefix, tree = nil)
|
81
110
|
http = Net::HTTP.start(@server_ip, @server_port)
|
82
111
|
request = Net::HTTP::Get.new("#{url_prefix}/api/json")
|
112
|
+
puts "[DEBUG] debug value is: #{@debug}"
|
113
|
+
puts "[INFO] GET #{url_prefix}/api/json" if @debug
|
83
114
|
request = Net::HTTP::Get.new("#{url_prefix}/api/json?#{tree}") if tree
|
84
115
|
request.basic_auth @username, @password
|
85
116
|
response = http.request(request)
|
@@ -104,6 +135,7 @@ module JenkinsApi
|
|
104
135
|
def api_post_request(url_prefix)
|
105
136
|
http = Net::HTTP.start(@server_ip, @server_port)
|
106
137
|
request = Net::HTTP::Post.new("#{url_prefix}")
|
138
|
+
puts "[INFO] PUT #{url_prefix}" if @debug
|
107
139
|
request.basic_auth @username, @password
|
108
140
|
response = http.request(request)
|
109
141
|
case response.code.to_i
|
@@ -125,6 +157,7 @@ module JenkinsApi
|
|
125
157
|
def get_config(url_prefix)
|
126
158
|
http = Net::HTTP.start(@server_ip, @server_port)
|
127
159
|
request = Net::HTTP::Get.new("#{url_prefix}/config.xml")
|
160
|
+
puts "[INFO] GET #{url_prefix}/config.xml" if @debug
|
128
161
|
request.basic_auth @username, @password
|
129
162
|
response = http.request(request)
|
130
163
|
response.body
|
@@ -138,6 +171,7 @@ module JenkinsApi
|
|
138
171
|
def post_config(url_prefix, xml)
|
139
172
|
http = Net::HTTP.start(@server_ip, @server_port)
|
140
173
|
request = Net::HTTP::Post.new("#{url_prefix}")
|
174
|
+
puts "[INFO] PUT #{url_prefix}" if @debug
|
141
175
|
request.basic_auth @username, @password
|
142
176
|
request.body = xml
|
143
177
|
request.content_type = 'application/xml'
|
@@ -124,15 +124,12 @@ module JenkinsApi
|
|
124
124
|
response_json["builds"]
|
125
125
|
end
|
126
126
|
|
127
|
-
#
|
128
|
-
# By defaule Jenkins returns the color of the job status icon
|
129
|
-
# This function translates the color into a meaningful status
|
127
|
+
# This method maps the color to status of a job
|
130
128
|
#
|
131
|
-
# @param [String]
|
129
|
+
# @param [String] color color given by the API for a job
|
132
130
|
#
|
133
|
-
def
|
134
|
-
|
135
|
-
case response_json["color"]
|
131
|
+
def color_to_status(color)
|
132
|
+
case color
|
136
133
|
when "blue"
|
137
134
|
"success"
|
138
135
|
when "red"
|
@@ -145,16 +142,29 @@ module JenkinsApi
|
|
145
142
|
"not run"
|
146
143
|
when "aborted"
|
147
144
|
"aborted"
|
145
|
+
else
|
146
|
+
"invalid"
|
148
147
|
end
|
149
148
|
end
|
150
149
|
|
150
|
+
# Obtain the current build status of the job
|
151
|
+
# By defaule Jenkins returns the color of the job status icon
|
152
|
+
# This function translates the color into a meaningful status
|
153
|
+
#
|
154
|
+
# @param [String] job_name
|
155
|
+
#
|
156
|
+
def get_current_build_status(job_name)
|
157
|
+
response_json = @client.api_get_request("/job/#{job_name}")
|
158
|
+
color_to_status(response_json["color"])
|
159
|
+
end
|
160
|
+
|
151
161
|
# This functions lists all jobs that are currently running on the Jenkins CI server
|
152
162
|
#
|
153
163
|
def list_running
|
154
164
|
xml_response = @client.api_get_request("", "tree=jobs[name,color]")
|
155
165
|
running_jobs = []
|
156
166
|
xml_response["jobs"].each { |job|
|
157
|
-
running_jobs << job["name"] if job["color"]
|
167
|
+
running_jobs << job["name"] if color_to_status(job["color"]) == "running"
|
158
168
|
}
|
159
169
|
running_jobs
|
160
170
|
end
|
@@ -292,6 +302,17 @@ module JenkinsApi
|
|
292
302
|
post_config(job_name, xml_modified)
|
293
303
|
end
|
294
304
|
|
305
|
+
# Unchain any existing chain between given job names
|
306
|
+
#
|
307
|
+
# @param [Array] job_names Array of job names to be unchained
|
308
|
+
#
|
309
|
+
def unchain(job_names)
|
310
|
+
job_names.each { |job|
|
311
|
+
puts "[INFO] Removing downstream projects for <#{job}>" if @client.debug
|
312
|
+
@client.job.remove_downstream_projects(job)
|
313
|
+
}
|
314
|
+
end
|
315
|
+
|
295
316
|
# Chain the jobs given based on specified criteria
|
296
317
|
#
|
297
318
|
# @param [Array] job_names Array of job names to be chained
|
@@ -301,24 +322,19 @@ module JenkinsApi
|
|
301
322
|
#
|
302
323
|
def chain(job_names, threshold, criteria, parallel = 1)
|
303
324
|
raise "Parallel jobs should be at least 1" if parallel < 1
|
304
|
-
|
305
|
-
job_names.each { |job|
|
306
|
-
puts "INFO: Removing downstream projects for <#{job}>" if @client.debug
|
307
|
-
@client.job.remove_downstream_projects(job)
|
308
|
-
}
|
309
|
-
|
325
|
+
unchain(job_names)
|
310
326
|
filtered_job_names = []
|
311
327
|
if criteria.include?("all") || criteria.empty?
|
312
328
|
filtered_job_names = job_names
|
313
329
|
else
|
314
|
-
puts "INFO
|
330
|
+
puts "[INFO] Criteria is specified. Filtering jobs..." if @client.debug
|
315
331
|
job_names.each { |job|
|
316
332
|
filtered_job_names << job if criteria.include?(@client.job.get_current_build_status(job))
|
317
333
|
}
|
318
334
|
end
|
319
335
|
filtered_job_names.each_with_index { |job_name, index|
|
320
336
|
break if index >= (filtered_job_names.length - parallel)
|
321
|
-
puts "INFO
|
337
|
+
puts "[INFO] Adding <#{filtered_job_names[index+1]}> as a downstream project to <#{job_name}> with <#{threshold}> as the threshold" if @client.debug
|
322
338
|
@client.job.add_downstream_projects(job_name, filtered_job_names[index + parallel], threshold, true)
|
323
339
|
}
|
324
340
|
parallel = filtered_job_names.length if parallel > filtered_job_names.length
|
@@ -0,0 +1,149 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 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
|
+
class Node
|
26
|
+
|
27
|
+
# General attributes of a node.
|
28
|
+
# This allows the following methods to be called on this node object.
|
29
|
+
# These methods are defined using define_method and are prefixed
|
30
|
+
# with get_.
|
31
|
+
#
|
32
|
+
# def get_busyExecutors
|
33
|
+
# def get_displayName
|
34
|
+
# def get_totalExecutors
|
35
|
+
#
|
36
|
+
GENERAL_ATTRIBUTES = [
|
37
|
+
"busyExecutors",
|
38
|
+
"displayName",
|
39
|
+
"totalExecutors"
|
40
|
+
]
|
41
|
+
|
42
|
+
# Properties of a node.
|
43
|
+
# The following methods are defined to be called on the node object
|
44
|
+
# and are prefixed with is_ and end with ? as they return true or false.
|
45
|
+
#
|
46
|
+
# def is_idle?(node_name)
|
47
|
+
# def is_jnlpAgent?(node_name)
|
48
|
+
# def is_launchSupported?(node_name)
|
49
|
+
# def is_manualLaunchAllowed?(node_name)
|
50
|
+
# def is_offline?(node_name)
|
51
|
+
# def is_temporarilyOffline?(node_name)
|
52
|
+
#
|
53
|
+
NODE_PROPERTIES = [
|
54
|
+
"idle",
|
55
|
+
"jnlpAgent",
|
56
|
+
"launchSupported",
|
57
|
+
"manualLaunchAllowed",
|
58
|
+
"offline",
|
59
|
+
"temporarilyOffline"
|
60
|
+
]
|
61
|
+
|
62
|
+
# Node specific attributes.
|
63
|
+
# The following methods are defined using define_method.
|
64
|
+
# These methods are prefixed with get_node_.
|
65
|
+
#
|
66
|
+
# def get_node_numExecutors(node_name)
|
67
|
+
# def get_node_icon(node_name)
|
68
|
+
# def get_node_displayName(node_name)
|
69
|
+
# def get_node_loadStatistics(node_name)
|
70
|
+
# def get_node_monitorData(node_name)
|
71
|
+
# def get_node_offlineCause(node_name)
|
72
|
+
# def get_node_oneOffExecutors(node_name)
|
73
|
+
#
|
74
|
+
NODE_ATTRIBUTES = [
|
75
|
+
"numExecutors",
|
76
|
+
"icon",
|
77
|
+
"displayName",
|
78
|
+
"loadStatistics",
|
79
|
+
"monitorData",
|
80
|
+
"offlineCause",
|
81
|
+
"oneOffExecutors"
|
82
|
+
]
|
83
|
+
|
84
|
+
# Initializes a new node object
|
85
|
+
#
|
86
|
+
# @param [Object] client reference to Client
|
87
|
+
#
|
88
|
+
def initialize(client)
|
89
|
+
@client = client
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_s
|
93
|
+
"#<JenkinsApi::Client::Node>"
|
94
|
+
end
|
95
|
+
|
96
|
+
# This method lists all nodes
|
97
|
+
#
|
98
|
+
# @param [String] filter a regex to filter node names
|
99
|
+
# @param [Bool] ignorecase whether to be case sensitive or not
|
100
|
+
#
|
101
|
+
def list(filter = nil, ignorecase = true)
|
102
|
+
node_names = []
|
103
|
+
response_json = @client.api_get_request("/computer")
|
104
|
+
response_json["computer"].each { |computer|
|
105
|
+
node_names << computer["displayName"] if computer["displayName"] =~ /#{filter}/i
|
106
|
+
}
|
107
|
+
node_names
|
108
|
+
end
|
109
|
+
|
110
|
+
# Identifies the index of a node name in the array node nodes
|
111
|
+
#
|
112
|
+
# @param [String] node_name name of the node
|
113
|
+
#
|
114
|
+
def index(node_name)
|
115
|
+
response_json = @client.api_get_request("/computer")
|
116
|
+
response_json["computer"].each_with_index { |computer, index|
|
117
|
+
return index if computer["displayName"] == node_name
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
# Defines methods for general node attributes.
|
122
|
+
#
|
123
|
+
GENERAL_ATTRIBUTES.each do |meth_suffix|
|
124
|
+
define_method("get_#{meth_suffix}") do
|
125
|
+
response_json = @client.api_get_request("/computer")
|
126
|
+
response_json["#{meth_suffix}"]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Defines methods for node properties.
|
131
|
+
#
|
132
|
+
NODE_PROPERTIES.each do |meth_suffix|
|
133
|
+
define_method("is_#{meth_suffix}?") do |node_name|
|
134
|
+
response_json = @client.api_get_request("/computer")
|
135
|
+
response_json["computer"][index(node_name)]["#{meth_suffix}"] =~ /False/i ? false : true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Defines methods for node specific attributes.
|
140
|
+
NODE_ATTRIBUTES.each do |meth_suffix|
|
141
|
+
define_method("get_node_#{meth_suffix}") do |node_name|
|
142
|
+
response_json = @client.api_get_request("/computer")
|
143
|
+
response_json["computer"][index(node_name)]["#{meth_suffix}"]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|