Merge lp:~wgrant/launchpad/webhook-jobrunner into lp:launchpad

Proposed by William Grant
Status: Merged
Merged at revision: 17634
Proposed branch: lp:~wgrant/launchpad/webhook-jobrunner
Merge into: lp:launchpad
Prerequisite: lp:~wgrant/launchpad/webhook-api
Diff against target: 170 lines (+76/-12)
4 files modified
configs/testrunner/launchpad-lazr.conf (+1/-1)
lib/lp/services/webhooks/configure.zcml (+11/-7)
lib/lp/services/webhooks/model.py (+14/-1)
lib/lp/services/webhooks/tests/test_webhookjob.py (+50/-3)
To merge this branch: bzr merge lp:~wgrant/launchpad/webhook-jobrunner
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+264533@code.launchpad.net

Commit message

Fix and test cron and celery WebhookDeliveryJob running.

Description of the change

Some quick fixes and tests for running WebhookDeliveryJobs from the cronscript and celery.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'configs/testrunner/launchpad-lazr.conf'
--- configs/testrunner/launchpad-lazr.conf 2015-07-13 11:21:00 +0000
+++ configs/testrunner/launchpad-lazr.conf 2015-07-13 11:21:01 +0000
@@ -182,4 +182,4 @@
182root: /var/tmp/testkeyserver.test182root: /var/tmp/testkeyserver.test
183183
184[webhooks]184[webhooks]
185http_proxy: http://example.com:3128/185http_proxy: http://webhooks-proxy.invalid:3128/
186186
=== modified file 'lib/lp/services/webhooks/configure.zcml'
--- lib/lp/services/webhooks/configure.zcml 2015-07-13 11:21:00 +0000
+++ lib/lp/services/webhooks/configure.zcml 2015-07-13 11:21:01 +0000
@@ -16,19 +16,23 @@
16 <subscriber16 <subscriber
17 for="lp.services.webhooks.interfaces.IWebhook zope.lifecycleevent.interfaces.IObjectModifiedEvent"17 for="lp.services.webhooks.interfaces.IWebhook zope.lifecycleevent.interfaces.IObjectModifiedEvent"
18 handler="lp.services.webhooks.model.webhook_modified"/>18 handler="lp.services.webhooks.model.webhook_modified"/>
19
20 <class class="lp.services.webhooks.model.WebhookDeliveryJob">
21 <require
22 permission="launchpad.View"
23 interface="lp.services.webhooks.interfaces.IWebhookDeliveryJob"/>
24 </class>
25
26 <securedutility19 <securedutility
27 class="lp.services.webhooks.model.WebhookSource"20 class="lp.services.webhooks.model.WebhookSource"
28 provides="lp.services.webhooks.interfaces.IWebhookSource">21 provides="lp.services.webhooks.interfaces.IWebhookSource">
29 <allow interface="lp.services.webhooks.interfaces.IWebhookSource"/>22 <allow interface="lp.services.webhooks.interfaces.IWebhookSource"/>
30 </securedutility>23 </securedutility>
3124
25 <securedutility
26 component="lp.services.webhooks.model.WebhookDeliveryJob"
27 provides="lp.services.webhooks.interfaces.IWebhookDeliveryJobSource">
28 <allow interface="lp.services.webhooks.interfaces.IWebhookDeliveryJobSource"/>
29 </securedutility>
30 <class class="lp.services.webhooks.model.WebhookDeliveryJob">
31 <require
32 permission="launchpad.View"
33 interface="lp.services.webhooks.interfaces.IWebhookDeliveryJob"/>
34 </class>
35
32 <utility36 <utility
33 provides="lp.services.webhooks.interfaces.IWebhookClient"37 provides="lp.services.webhooks.interfaces.IWebhookClient"
34 factory="lp.services.webhooks.client.WebhookClient"38 factory="lp.services.webhooks.client.WebhookClient"
3539
=== modified file 'lib/lp/services/webhooks/model.py'
--- lib/lp/services/webhooks/model.py 2015-07-13 11:21:00 +0000
+++ lib/lp/services/webhooks/model.py 2015-07-13 11:21:01 +0000
@@ -41,7 +41,10 @@
41from lp.services.database.constants import UTC_NOW41from lp.services.database.constants import UTC_NOW
42from lp.services.database.decoratedresultset import DecoratedResultSet42from lp.services.database.decoratedresultset import DecoratedResultSet
43from lp.services.database.enumcol import EnumCol43from lp.services.database.enumcol import EnumCol
44from lp.services.database.interfaces import IStore44from lp.services.database.interfaces import (
45 IMasterStore,
46 IStore,
47 )
45from lp.services.database.stormbase import StormBase48from lp.services.database.stormbase import StormBase
46from lp.services.features import getFeatureFlag49from lp.services.features import getFeatureFlag
47from lp.services.job.model.job import (50from lp.services.job.model.job import (
@@ -242,6 +245,16 @@
242 def __init__(self, webhook_job):245 def __init__(self, webhook_job):
243 self.context = webhook_job246 self.context = webhook_job
244247
248 @classmethod
249 def iterReady(cls):
250 """See `IJobSource`."""
251 jobs = IMasterStore(WebhookJob).find(
252 WebhookJob,
253 WebhookJob.job_type == cls.class_job_type,
254 WebhookJob.job == Job.id,
255 Job.id.is_in(Job.ready_jobs))
256 return (cls(job) for job in jobs)
257
245258
246@provider(IWebhookDeliveryJobSource)259@provider(IWebhookDeliveryJobSource)
247@implementer(IWebhookDeliveryJob)260@implementer(IWebhookDeliveryJob)
248261
=== modified file 'lib/lp/services/webhooks/tests/test_webhookjob.py'
--- lib/lp/services/webhooks/tests/test_webhookjob.py 2015-07-13 11:21:00 +0000
+++ lib/lp/services/webhooks/tests/test_webhookjob.py 2015-07-13 11:21:01 +0000
@@ -21,9 +21,13 @@
21 MatchesStructure,21 MatchesStructure,
22 Not,22 Not,
23 )23 )
24import transaction
2425
26from lp.services.features.testing import FeatureFixture
25from lp.services.job.interfaces.job import JobStatus27from lp.services.job.interfaces.job import JobStatus
26from lp.services.job.runner import JobRunner28from lp.services.job.runner import JobRunner
29from lp.services.job.tests import block_on_job
30from lp.services.scripts.tests import run_script
27from lp.services.webhooks.client import WebhookClient31from lp.services.webhooks.client import WebhookClient
28from lp.services.webhooks.interfaces import (32from lp.services.webhooks.interfaces import (
29 IWebhookClient,33 IWebhookClient,
@@ -43,8 +47,9 @@
43 ZopeUtilityFixture,47 ZopeUtilityFixture,
44 )48 )
45from lp.testing.layers import (49from lp.testing.layers import (
50 CeleryJobLayer,
46 DatabaseFunctionalLayer,51 DatabaseFunctionalLayer,
47 LaunchpadZopelessLayer,52 ZopelessDatabaseLayer,
48 )53 )
4954
5055
@@ -63,7 +68,7 @@
63class TestWebhookJobDerived(TestCaseWithFactory):68class TestWebhookJobDerived(TestCaseWithFactory):
64 """Tests for `WebhookJobDerived`."""69 """Tests for `WebhookJobDerived`."""
6570
66 layer = LaunchpadZopelessLayer71 layer = DatabaseFunctionalLayer
6772
68 def test_getOopsMailController(self):73 def test_getOopsMailController(self):
69 """By default, no mail is sent about failed WebhookJobs."""74 """By default, no mail is sent about failed WebhookJobs."""
@@ -147,7 +152,7 @@
147class TestWebhookDeliveryJob(TestCaseWithFactory):152class TestWebhookDeliveryJob(TestCaseWithFactory):
148 """Tests for `WebhookDeliveryJob`."""153 """Tests for `WebhookDeliveryJob`."""
149154
150 layer = LaunchpadZopelessLayer155 layer = ZopelessDatabaseLayer
151156
152 def makeAndRunJob(self, response_status=200, raises=None, mock=True):157 def makeAndRunJob(self, response_status=200, raises=None, mock=True):
153 hook = self.factory.makeWebhook(delivery_url=u'http://hookep.com/foo')158 hook = self.factory.makeWebhook(delivery_url=u'http://hookep.com/foo')
@@ -251,3 +256,45 @@
251 self.assertEqual(1, len(oopses.oopses))256 self.assertEqual(1, len(oopses.oopses))
252 self.assertEqual(257 self.assertEqual(
253 'No webhook proxy configured.', oopses.oopses[0]['value'])258 'No webhook proxy configured.', oopses.oopses[0]['value'])
259
260
261class TestViaCronscript(TestCaseWithFactory):
262
263 layer = ZopelessDatabaseLayer
264
265 def test_run_from_cronscript(self):
266 hook = self.factory.makeWebhook(delivery_url=u'http://hookep.com/foo')
267 job = WebhookDeliveryJob.create(hook, payload={'foo': 'bar'})
268 self.assertEqual(JobStatus.WAITING, job.status)
269 transaction.commit()
270
271 retcode, stdout, stderr = run_script(
272 'cronscripts/process-job-source.py', ['IWebhookDeliveryJobSource'],
273 expect_returncode=0)
274 self.assertEqual('', stdout)
275 self.assertIn('INFO Ran 1 WebhookDeliveryJob jobs.\n', stderr)
276
277 self.assertEqual(JobStatus.COMPLETED, job.status)
278 self.assertIn(
279 'Cannot connect to proxy',
280 job.json_data['result']['connection_error'])
281
282
283class TestViaCelery(TestCaseWithFactory):
284
285 layer = CeleryJobLayer
286
287 def test_WebhookDeliveryJob(self):
288 """WebhookDeliveryJob runs under Celery."""
289 hook = self.factory.makeWebhook(delivery_url=u'http://hookep.com/foo')
290
291 self.useFixture(FeatureFixture(
292 {'jobs.celery.enabled_classes': 'WebhookDeliveryJob'}))
293 with block_on_job():
294 job = WebhookDeliveryJob.create(hook, payload={'foo': 'bar'})
295 transaction.commit()
296
297 self.assertEqual(JobStatus.COMPLETED, job.status)
298 self.assertIn(
299 'Cannot connect to proxy',
300 job.json_data['result']['connection_error'])