Add a get_nodes method
Until now it has not been possible to enumerate build nodes connected to the master. This commit adds the support via get_nodes() method, which returns a list of dicts with name and offline-status for the nodes. Signed-off-by: Antoine Musso <hashar@free.fr> Change-Id: Ia51ee71196a80e365693959edac860730e7ea202
This commit is contained in:
committed by
Antoine Musso
parent
0632d046b1
commit
b66509d5df
@@ -81,7 +81,7 @@ STOP_BUILD = 'job/%(name)s/%(number)s/stop'
|
|||||||
BUILD_WITH_PARAMS_JOB = 'job/%(name)s/buildWithParameters'
|
BUILD_WITH_PARAMS_JOB = 'job/%(name)s/buildWithParameters'
|
||||||
BUILD_INFO = 'job/%(name)s/%(number)d/api/json?depth=%(depth)s'
|
BUILD_INFO = 'job/%(name)s/%(number)d/api/json?depth=%(depth)s'
|
||||||
BUILD_CONSOLE_OUTPUT = 'job/%(name)s/%(number)d/consoleText'
|
BUILD_CONSOLE_OUTPUT = 'job/%(name)s/%(number)d/consoleText'
|
||||||
|
NODE_LIST = 'computer/api/json'
|
||||||
CREATE_NODE = 'computer/doCreateItem?%s'
|
CREATE_NODE = 'computer/doCreateItem?%s'
|
||||||
DELETE_NODE = 'computer/%(name)s/doDelete'
|
DELETE_NODE = 'computer/%(name)s/doDelete'
|
||||||
NODE_INFO = 'computer/%(name)s/api/json?depth=%(depth)s'
|
NODE_INFO = 'computer/%(name)s/api/json?depth=%(depth)s'
|
||||||
@@ -648,6 +648,24 @@ class Jenkins(object):
|
|||||||
'''
|
'''
|
||||||
self.jenkins_open(Request(self.server + STOP_BUILD % self._get_encoded_params(locals())))
|
self.jenkins_open(Request(self.server + STOP_BUILD % self._get_encoded_params(locals())))
|
||||||
|
|
||||||
|
def get_nodes(self):
|
||||||
|
'''Get a list of nodes connected to the Master
|
||||||
|
|
||||||
|
Each node is a dict with keys 'name' and 'offline'
|
||||||
|
|
||||||
|
:returns: List of nodes, ``[ { str: str, str: bool} ]``
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
nodes_data = json.loads(self.jenkins_open(Request(self.server + NODE_LIST)))
|
||||||
|
return [{'name': c["displayName"], 'offline': c["offline"]}
|
||||||
|
for c in nodes_data["computer"]]
|
||||||
|
except (HTTPError, BadStatusLine):
|
||||||
|
raise BadHTTPException("Error communicating with server[%s]"
|
||||||
|
% self.server)
|
||||||
|
except ValueError:
|
||||||
|
raise JenkinsException("Could not parse JSON info for server[%s]"
|
||||||
|
% self.server)
|
||||||
|
|
||||||
def get_node_info(self, name, depth=0):
|
def get_node_info(self, name, depth=0):
|
||||||
'''Get node information dictionary
|
'''Get node information dictionary
|
||||||
|
|
||||||
|
|||||||
@@ -1144,6 +1144,63 @@ class JenkinsTest(unittest.TestCase):
|
|||||||
jenkins_mock.call_args[0][0].get_full_url(),
|
jenkins_mock.call_args[0][0].get_full_url(),
|
||||||
u'http://example.com/queue/cancelItem?id=52')
|
u'http://example.com/queue/cancelItem?id=52')
|
||||||
|
|
||||||
|
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
||||||
|
def test_get_nodes(self, jenkins_mock):
|
||||||
|
jenkins_mock.return_value = json.dumps({
|
||||||
|
"computer": [{
|
||||||
|
"displayName": "master",
|
||||||
|
"offline": False
|
||||||
|
}],
|
||||||
|
"busyExecutors": 2})
|
||||||
|
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
|
||||||
|
self.assertEqual(j.get_nodes(),
|
||||||
|
[{'name': 'master', 'offline': False}])
|
||||||
|
|
||||||
|
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
||||||
|
def test_get_nodes__invalid_json(self, jenkins_mock):
|
||||||
|
jenkins_mock.side_effect = [
|
||||||
|
'Invalid JSON',
|
||||||
|
]
|
||||||
|
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
|
||||||
|
|
||||||
|
with self.assertRaises(jenkins.JenkinsException) as context_manager:
|
||||||
|
j.get_nodes()
|
||||||
|
self.assertEqual(
|
||||||
|
jenkins_mock.call_args[0][0].get_full_url(),
|
||||||
|
'http://example.com/computer/api/json')
|
||||||
|
self.assertEqual(
|
||||||
|
str(context_manager.exception),
|
||||||
|
'Could not parse JSON info for server[http://example.com/]')
|
||||||
|
|
||||||
|
@patch('jenkins.urlopen')
|
||||||
|
def test_get_nodes__BadStatusLine(self, urlopen_mock):
|
||||||
|
urlopen_mock.side_effect = jenkins.BadStatusLine('not a valid status line')
|
||||||
|
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
|
||||||
|
with self.assertRaises(jenkins.BadHTTPException) as context_manager:
|
||||||
|
j.get_nodes()
|
||||||
|
self.assertEqual(
|
||||||
|
str(context_manager.exception),
|
||||||
|
'Error communicating with server[http://example.com/]')
|
||||||
|
|
||||||
|
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
||||||
|
def test_get_nodes__HTTPError(self, jenkins_mock):
|
||||||
|
jenkins_mock.side_effect = jenkins.HTTPError(
|
||||||
|
'http://example.com/job/TestJob',
|
||||||
|
code=401,
|
||||||
|
msg="basic auth failed",
|
||||||
|
hdrs=[],
|
||||||
|
fp=None)
|
||||||
|
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
|
||||||
|
|
||||||
|
with self.assertRaises(jenkins.JenkinsException) as context_manager:
|
||||||
|
j.get_nodes()
|
||||||
|
self.assertEqual(
|
||||||
|
jenkins_mock.call_args[0][0].get_full_url(),
|
||||||
|
'http://example.com/computer/api/json')
|
||||||
|
self.assertEqual(
|
||||||
|
str(context_manager.exception),
|
||||||
|
'Error communicating with server[http://example.com/]')
|
||||||
|
|
||||||
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
||||||
def test_get_node_info(self, jenkins_mock):
|
def test_get_node_info(self, jenkins_mock):
|
||||||
node_info = {
|
node_info = {
|
||||||
|
|||||||
Reference in New Issue
Block a user