From 284c3d37b70770462cb32b34026f6ef5e8140ec2 Mon Sep 17 00:00:00 2001 From: Ken Dreyer Date: Tue, 17 Apr 2018 02:52:51 -0600 Subject: [PATCH] add get_queue_item() method Pass in a queue ID number to discover a job's status, and possibly a job URL. Change-Id: I20541ec49cc30e5c74a6c596e02b3f42b2567fa5 Closes-Bug: #1724932 --- jenkins/__init__.py | 35 +++++++++++++++++++++++++++++++++++ tests/test_queue.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/jenkins/__init__.py b/jenkins/__init__.py index 94b178e..3b92ddc 100755 --- a/jenkins/__init__.py +++ b/jenkins/__init__.py @@ -101,6 +101,7 @@ JOB_INFO = '%(folder_url)sjob/%(short_name)s/api/json?depth=%(depth)s' JOB_NAME = '%(folder_url)sjob/%(short_name)s/api/json?tree=name' ALL_BUILDS = '%(folder_url)sjob/%(short_name)s/api/json?tree=allBuilds[number,url]' Q_INFO = 'queue/api/json?depth=0' +Q_ITEM = 'queue/item/%(number)d/api/json' CANCEL_QUEUE = 'queue/cancelItem?id=%(id)s' CREATE_JOB = '%(folder_url)screateItem?name=%(short_name)s' # also post config.xml CONFIG_JOB = '%(folder_url)sjob/%(short_name)s/config.xml' @@ -572,6 +573,34 @@ class Jenkins(object): raise TimeoutException('Error in request: %s' % (e.reason)) raise JenkinsException('Error in request: %s' % (e.reason)) + def get_queue_item(self, number): + '''Get information about a queued item (to-be-created job). + + The returned dict will have a "why" key if the queued item is still + waiting for an executor. + + The returned dict will have an "executable" key if the queued item is + running on an executor, or has completed running. Use this to + determine the job number / URL. + + :param name: queue number, ``int`` + :returns: dictionary of queued information, ``dict`` + ''' + url = self._build_url(Q_ITEM, locals()) + try: + response = self.jenkins_open(requests.Request('GET', url)) + if response: + return json.loads(response) + else: + raise JenkinsException('queue number[%d] does not exist' + % number) + except (req_exc.HTTPError, NotFoundException): + raise JenkinsException('queue number[%d] does not exist' % number) + except ValueError: + raise JenkinsException( + 'Could not parse JSON info for queue number[%d]' % number + ) + def get_build_info(self, name, number, depth=0): '''Get build information dictionary. @@ -1172,6 +1201,12 @@ class Jenkins(object): def build_job(self, name, parameters=None, token=None): '''Trigger build job. + This method returns a queue item number that you can pass to + :meth:`Jenkins.get_queue_item`. Note that this queue number is only + valid for about five minutes after the job completes, so you should + get/poll the queue information as soon as possible to determine the + job's URL. + :param name: name of job :param parameters: parameters for job, or ``None``, ``dict`` :param token: Jenkins API token diff --git a/tests/test_queue.py b/tests/test_queue.py index a40d20c..7502fb1 100644 --- a/tests/test_queue.py +++ b/tests/test_queue.py @@ -70,3 +70,42 @@ class JenkinsQueueInfoTest(JenkinsTestBase): jenkins_mock.call_args[0][0].url, self.make_url('queue/api/json?depth=0')) self._check_requests(jenkins_mock.call_args_list) + + +class JenkinsQueueItemTest(JenkinsTestBase): + @patch.object(jenkins.Jenkins, 'jenkins_open') + def test_simple(self, jenkins_mock): + queue_item_to_return = { + u'_class': u'hudson.model.Queue$LeftItem', + u'actions': [{u'_class': u'hudson.model.CauseAction', + u'causes': [{u'_class': u'hudson.model.Cause$UserIdCause', + u'shortDescription': u'Started by user Bob', + u'userId': u'bsmith', + u'userName': u'Bob'}]}], + u'blocked': False, + u'buildable': False, + u'cancelled': False, + u'executable': {u'_class': u'hudson.model.FreeStyleBuild', + u'number': 198, + u'url': u'http://your_url/job/my_job/198/'}, + u'id': 25, + u'inQueueSince': 1507914654469, + u'params': u'', + u'stuck': False, + u'task': {u'_class': u'hudson.model.FreeStyleProject', + u'color': u'red', + u'name': u'my_job', + u'url': u'http://your_url/job/my_job/'}, + u'url': u'queue/item/25/', + u'why': None, + } + + jenkins_mock.return_value = json.dumps(queue_item_to_return) + + queue_item = self.j.get_queue_item(25) + + self.assertEqual(queue_item, queue_item_to_return) + self.assertEqual( + jenkins_mock.call_args[0][0].url, + self.make_url('queue/item/25/api/json')) + self._check_requests(jenkins_mock.call_args_list)