Adds possibility to retrieve all jobs from the view specified

This patch adds the new `view_name` argument
to the `get_jobs` method that limits the list of jobs
returned to only those configured in the view specified.

Change-Id: I78266ed13cd6c183a2f4858458817455b79d9a23
This commit is contained in:
Aliaksandr Buhayeu 2016-02-12 22:40:56 +03:00
parent 6728d36463
commit f6f26ec481
3 changed files with 149 additions and 3 deletions

View File

@ -86,6 +86,10 @@ This is an example showing how to create, configure and delete Jenkins jobs.
build_info = server.get_job_info('api-test', last_build_number)
print build_info
# get all jobs from the specific view
jobs = server.get_jobs(view_name='View Name')
print jobs
Example 4: Working with Jenkins Views
-------------------------------------

View File

@ -116,6 +116,7 @@ NODE_TYPE = 'hudson.slaves.DumbSlave$DescriptorImpl'
TOGGLE_OFFLINE = 'computer/%(name)s/toggleOffline?offlineMessage=%(msg)s'
CONFIG_NODE = 'computer/%(name)s/config.xml'
VIEW_NAME = 'view/%(name)s/api/json?tree=name'
VIEW_JOBS = 'view/%(name)s/api/json?tree=jobs[url,color,name]'
CREATE_VIEW = 'createView?name=%(name)s'
CONFIG_VIEW = 'view/%(name)s/config.xml'
DELETE_VIEW = 'view/%(name)s/doDelete'
@ -657,18 +658,41 @@ class Jenkins(object):
return plugins_data
def get_jobs(self, folder_depth=0):
def get_jobs(self, folder_depth=0, view_name=None):
"""Get list of jobs.
Each job is a dictionary with 'name', 'url', 'color' and 'fullname'
keys.
If the ``view_name`` parameter is present, the list of
jobs will be limited to only those configured in the
specified view. In this case, the job dictionary 'fullname' key
would be equal to the job name.
:param folder_depth: Number of levels to search, ``int``. By default
0, which will limit search to toplevel. None disables the limit.
:returns: list of jobs, ``[ { str: str} ]``
:param view_name: Name of a Jenkins view for which to
retrieve jobs, ``str``. By default, the job list is
not limited to a specific view.
:returns: list of jobs, ``[{str: str, str: str, str: str, str: str}]``
Example::
>>> jobs = server.get_jobs()
>>> print(jobs)
[{
u'name': u'all_tests',
u'url': u'http://your_url.here/job/all_tests/',
u'color': u'blue',
u'fullname': u'all_tests'
}]
"""
return self.get_all_jobs(folder_depth=folder_depth)
if view_name:
return self._get_view_jobs(view_name=view_name)
else:
return self.get_all_jobs(folder_depth=folder_depth)
def get_all_jobs(self, folder_depth=None):
"""Get list of all jobs recursively to the given folder depth.
@ -1268,6 +1292,40 @@ class Jenkins(object):
return folder_url, short_name
def _get_view_jobs(self, view_name):
'''Get list of jobs on the view specified.
Each job is a dictionary with 'name', 'url', 'color' and 'fullname'
keys.
The list of jobs is limited to only those configured in the
specified view. Each job dictionary 'fullname' key
is equal to the job name.
:param view_name: Name of a Jenkins view for which to
retrieve jobs, ``str``.
:returns: list of jobs, ``[{str: str, str: str, str: str, str: str}]``
'''
try:
response = self.jenkins_open(Request(
self._build_url(VIEW_JOBS, {u'name': view_name})
))
if response:
jobs = json.loads(response)['jobs']
else:
raise JenkinsException('view[%s] does not exist' % view_name)
except HTTPError:
raise JenkinsException('view[%s] does not exist' % view_name)
except ValueError:
raise JenkinsException(
'Could not parse JSON info for view[%s]' % view_name)
for job_dict in jobs:
job_dict.update({u'fullname': job_dict[u'name']})
return jobs
def get_view_name(self, name):
'''Return the name of a view using the API.

View File

@ -57,3 +57,87 @@ class JenkinsGetJobsTest(JenkinsGetJobsTestBase):
self.assertEqual(len(expected_fullnames), len(jobs_info))
got_fullnames = [job[u"fullname"] for job in jobs_info]
self.assertEqual(expected_fullnames, got_fullnames)
@patch.object(jenkins.Jenkins, 'jenkins_open')
def test_get_view_jobs(self, jenkins_mock):
view_jobs_to_return = {
u'jobs': [{
u'name': u'community.all',
u'url': u'http://your_url_here',
u'color': u'grey'
}, {
u'name': u'community.first',
u'url': u'http://your_url_here',
u'color': u'red'
}]
}
jenkins_mock.return_value = json.dumps(view_jobs_to_return)
view_jobs = self.j.get_jobs(view_name=u'Test View')
self.assertEqual(view_jobs[0][u'color'], u'grey')
self.assertEqual(view_jobs[1][u'name'], u'community.first')
self.assertEqual(view_jobs[1][u'name'], view_jobs[1][u'fullname'])
self.assertEqual(
jenkins_mock.call_args[0][0].get_full_url(),
self.make_url(
'view/Test%20View/api/json?tree=jobs[url,color,name]'
))
self._check_requests(jenkins_mock.call_args_list)
@patch.object(jenkins.Jenkins, 'jenkins_open')
def test_get_view_jobs_return_none(self, jenkins_mock):
jenkins_mock.return_value = None
with self.assertRaises(jenkins.JenkinsException) as context_manager:
self.j.get_jobs(view_name=u'Test View')
self.assertEqual(
jenkins_mock.call_args[0][0].get_full_url(),
self.make_url(
'view/Test%20View/api/json?tree=jobs[url,color,name]'
))
self.assertEqual(
str(context_manager.exception),
'view[Test View] does not exist')
self._check_requests(jenkins_mock.call_args_list)
@patch.object(jenkins.Jenkins, 'jenkins_open')
def test_get_view_jobs_return_invalid_json(self, jenkins_mock):
jenkins_mock.return_value = 'Invalid JSON'
with self.assertRaises(jenkins.JenkinsException) as context_manager:
self.j.get_jobs(view_name=u'Test View')
self.assertEqual(
jenkins_mock.call_args[0][0].get_full_url(),
self.make_url(
'view/Test%20View/api/json?tree=jobs[url,color,name]'
))
self.assertEqual(
str(context_manager.exception),
'Could not parse JSON info for view[Test View]')
self._check_requests(jenkins_mock.call_args_list)
@patch.object(jenkins.Jenkins, 'jenkins_open')
def test_get_view_jobs_raise_HTTPError(self, jenkins_mock):
jenkins_mock.side_effect = jenkins.HTTPError(
self.make_url(
'view/Test%20View/api/json?tree=jobs[url,color,name]'),
code=401,
msg="basic auth failed",
hdrs=[],
fp=None)
with self.assertRaises(jenkins.JenkinsException) as context_manager:
self.j.get_jobs(view_name=u'Test View')
self.assertEqual(
jenkins_mock.call_args[0][0].get_full_url(),
self.make_url(
'view/Test%20View/api/json?tree=jobs[url,color,name]'
))
self.assertEqual(
str(context_manager.exception),
'view[Test View] does not exist')
self._check_requests(jenkins_mock.call_args_list)