From 46546366eb4e770bcb365848ab836d609cd546e3 Mon Sep 17 00:00:00 2001 From: Salim Fadhley Date: Sun, 3 Aug 2014 17:36:39 +0100 Subject: [PATCH] Lots of fixes --- jenkinsapi/custom_exceptions.py | 28 ++++++++++++++ jenkinsapi/job.py | 40 ++++++++++---------- jenkinsapi/queue.py | 2 +- jenkinsapi_tests/systests/test_invocation.py | 7 ++++ jenkinsapi_tests/unittests/test_job.py | 3 +- 5 files changed, 59 insertions(+), 21 deletions(-) diff --git a/jenkinsapi/custom_exceptions.py b/jenkinsapi/custom_exceptions.py index 69009ad..5582900 100644 --- a/jenkinsapi/custom_exceptions.py +++ b/jenkinsapi/custom_exceptions.py @@ -4,6 +4,7 @@ Module for custom_exceptions specialized for jenkinsapi class JenkinsAPIException(Exception): + """ Base class for all errors """ @@ -11,6 +12,7 @@ class JenkinsAPIException(Exception): class NotFound(JenkinsAPIException): + """ Resource cannot be found """ @@ -18,6 +20,7 @@ class NotFound(JenkinsAPIException): class ArtifactsMissing(NotFound): + """ Cannot find a build with all of the required artifacts. """ @@ -25,6 +28,7 @@ class ArtifactsMissing(NotFound): class UnknownJob(KeyError, NotFound): + """ Jenkins does not recognize the job requested. """ @@ -32,6 +36,7 @@ class UnknownJob(KeyError, NotFound): class UnknownView(KeyError, NotFound): + """ Jenkins does not recognize the view requested. """ @@ -39,6 +44,7 @@ class UnknownView(KeyError, NotFound): class UnknownNode(KeyError, NotFound): + """ Jenkins does not recognize the node requested. """ @@ -46,6 +52,7 @@ class UnknownNode(KeyError, NotFound): class UnknownQueueItem(KeyError, NotFound): + """ Jenkins does not recognize the requested queue item """ @@ -53,6 +60,7 @@ class UnknownQueueItem(KeyError, NotFound): class UnknownPlugin(KeyError, NotFound): + """ Jenkins does not recognize the plugin requested. """ @@ -60,6 +68,7 @@ class UnknownPlugin(KeyError, NotFound): class NoBuildData(NotFound): + """ A job has no build data. """ @@ -67,6 +76,7 @@ class NoBuildData(NotFound): class NotBuiltYet(NotFound): + """ A job has no build data. """ @@ -74,6 +84,7 @@ class NotBuiltYet(NotFound): class ArtifactBroken(JenkinsAPIException): + """ An artifact is broken, wrong """ @@ -81,6 +92,7 @@ class ArtifactBroken(JenkinsAPIException): class TimeOut(JenkinsAPIException): + """ Some jobs have taken too long to complete. """ @@ -88,6 +100,7 @@ class TimeOut(JenkinsAPIException): class NoResults(JenkinsAPIException): + """ A build did not publish any results. """ @@ -95,6 +108,7 @@ class NoResults(JenkinsAPIException): class FailedNoResults(NoResults): + """ A build did not publish any results because it failed """ @@ -102,6 +116,7 @@ class FailedNoResults(NoResults): class BadURL(ValueError, JenkinsAPIException): + """ A URL appears to be broken """ @@ -109,12 +124,14 @@ class BadURL(ValueError, JenkinsAPIException): class NotAuthorized(JenkinsAPIException): + """Not Authorized to access resource""" # Usually thrown when we get a 403 returned pass class NotSupportSCM(JenkinsAPIException): + """ It's a SCM that does not supported by current version of jenkinsapi """ @@ -122,6 +139,7 @@ class NotSupportSCM(JenkinsAPIException): class NotConfiguredSCM(JenkinsAPIException): + """ It's a job that doesn't have configured SCM """ @@ -129,6 +147,7 @@ class NotConfiguredSCM(JenkinsAPIException): class NotInQueue(JenkinsAPIException): + """ It's a job that is not in the queue """ @@ -136,7 +155,16 @@ class NotInQueue(JenkinsAPIException): class PostRequired(JenkinsAPIException): + """ Method requires POST and not GET """ pass + + +class BadParams(JenkinsAPIException): + + """ + Invocation was given bad or inappropriate params + """ + pass diff --git a/jenkinsapi/job.py b/jenkinsapi/job.py index f6aabc8..3f3056c 100644 --- a/jenkinsapi/job.py +++ b/jenkinsapi/job.py @@ -24,6 +24,7 @@ from jenkinsapi.custom_exceptions import ( NotInQueue, NotSupportSCM, UnknownQueueItem, + BadParams, ) SVN_URL = './scm/locations/hudson.scm.SubversionSCM_-ModuleLocation/remote' @@ -165,28 +166,24 @@ class Job(JenkinsBase, MutableJenkinsThing): def invoke(self, securitytoken=None, block=False, build_params=None, cause=None, files=None, delay=5): assert isinstance(block, bool) + if build_params and (not self.has_params()): + raise BadParams("This job does not support parameters") + + params = {} # Via Get string + + if securitytoken: + params['token'] = securitytoken # Either copy the params dict or make a new one. build_params = build_params and dict( build_params.items()) or {} # Via POSTed JSON - params = {} # Via Get string url = self.get_build_triggerurl() - # If job has file parameters - it must be triggered - # using "/build", not by "/buildWithParameters" - # "/buildWithParameters" will ignore non-file parameters - if files: - url = "%s/build" % self.baseurl - if cause: build_params['cause'] = cause - if securitytoken: - params['token'] = securitytoken - - build_params['json'] = self.mk_json_from_build_parameters( - build_params, files) - data = build_params + data = {'json': self.mk_json_from_build_parameters( + build_params, files)} response = self.jenkins.requester.post_url( url, @@ -196,12 +193,17 @@ class Job(JenkinsBase, MutableJenkinsThing): ) redirect_url = response.headers['location'] - if redirect_url.startswith("%s/queue/item" % self.jenkins.baseurl): - qi = QueueItem(redirect_url, self.jenkins) - if block: - qi.block_until_complete(delay=delay) - return qi - raise ValueError("Not a Queue URL: %s" % redirect_url) + + # It's possible that an error triggering the build will cause Jenkins + # not build, the signal is that we will be redirected to something + # other than a QueueItem URL. + if not redirect_url.startswith("%s/queue/item" % self.jenkins.baseurl): + raise ValueError("Not a Queue URL: %s" % redirect_url) + + qi = QueueItem(redirect_url, self.jenkins) + if block: + qi.block_until_complete(delay=delay) + return qi def _buildid_for_type(self, buildtype): """Gets a buildid for a given type of build""" diff --git a/jenkinsapi/queue.py b/jenkinsapi/queue.py index 7c04bb5..0bc0f5c 100644 --- a/jenkinsapi/queue.py +++ b/jenkinsapi/queue.py @@ -73,7 +73,7 @@ class Queue(JenkinsBase): return "%s/item/%i" % (self.baseurl, item["id"]) def delete_item(self, queue_item): - self.delete_item_by_id(queue_item.id) + self.delete_item_by_id(queue_item.queue_id) def delete_item_by_id(self, item_id): deleteurl = '%s/cancelItem?id=%s' % (self.baseurl, item_id) diff --git a/jenkinsapi_tests/systests/test_invocation.py b/jenkinsapi_tests/systests/test_invocation.py index 69e03aa..78c3692 100644 --- a/jenkinsapi_tests/systests/test_invocation.py +++ b/jenkinsapi_tests/systests/test_invocation.py @@ -14,6 +14,7 @@ from jenkinsapi_tests.systests.base import BaseSystemTest from jenkinsapi_tests.test_utils.random_strings import random_string from jenkinsapi_tests.systests.job_configs import LONG_RUNNING_JOB from jenkinsapi_tests.systests.job_configs import SHORTISH_JOB, EMPTY_JOB +from jenkinsapi.custom_exceptions import BadParams log = logging.getLogger(__name__) @@ -82,6 +83,12 @@ class TestInvocation(BaseSystemTest): build_number = qq.get_build_number() self.assertEquals(build_number, invocation + 1) + def test_give_params_on_non_parameterized_job(self): + job_name = 'Ecreate_%s' % random_string() + job = self.jenkins.create_job(job_name, EMPTY_JOB) + with self.assertRaises(BadParams): + job.invoke(build_params={'foo':'bar', 'baz':99}) + if __name__ == '__main__': # logging.basicConfig() diff --git a/jenkinsapi_tests/unittests/test_job.py b/jenkinsapi_tests/unittests/test_job.py index 3e427c6..7d30ca9 100644 --- a/jenkinsapi_tests/unittests/test_job.py +++ b/jenkinsapi_tests/unittests/test_job.py @@ -274,12 +274,13 @@ class TestJob(unittest.TestCase): get_data.return_value = TestJob.URL_DATA[url].copy() j = Job('http://halob:8080/job/foo/', 'foo', self.J) + self.assertTrue(j.has_params()) params = j.get_params_list() self.assertIsInstance(params, list) self.assertEquals(len(params), 2) self.assertEquals(params, ['param1', 'param2']) - + def test_get_build(self): buildnumber = 1 with mock.patch('jenkinsapi.job.Build') as build_mock: -- 2.34.1