Merge lp:~doanac/ubuntu-ci-services-itself/lander-sigterm into lp:ubuntu-ci-services-itself

Proposed by Andy Doan
Status: Merged
Approved by: Andy Doan
Approved revision: 342
Merged at revision: 354
Proposed branch: lp:~doanac/ubuntu-ci-services-itself/lander-sigterm
Merge into: lp:ubuntu-ci-services-itself
Diff against target: 42 lines (+13/-1)
2 files modified
lander/bin/lander_service_wrapper.py (+9/-1)
lander/bin/ticket_api.py (+4/-0)
To merge this branch: bzr merge lp:~doanac/ubuntu-ci-services-itself/lander-sigterm
Reviewer Review Type Date Requested Status
Andy Doan (community) Approve
Vincent Ladeuil (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+210073@code.launchpad.net

Commit message

lander: ensure ticket is marked failed when cancelled

We have an issue where a user might cancel a jenkins job, but the
lander fails to mark the ticket as failed. This can cause the same
ticket to get run again by the lander.

This checks SIGTERM (what jenkins sends when a job is cancelled)
and ensures the ticket is marked failed

Description of the change

Try and help ensure the lander marks a ticket as failed if a job gets canceled.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:342
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/346/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/346/rebuild

review: Approve (continuous-integration)
Revision history for this message
Vincent Ladeuil (vila) wrote :

19 + def _on_sigterm(signame, frame):
20 + logger.error('job was terminated, failing ticket')
21 + api.fail_ticket()

Just curious: what's the reason you define that function *inside* the other one ?

In practice, it often make them harder to test (you can't override them anymore).

review: Approve
Revision history for this message
Andy Doan (doanac) wrote :

On 03/09/2014 04:47 AM, Vincent Ladeuil wrote:
> 19 + def _on_sigterm(signame, frame):
> 20 + logger.error('job was terminated, failing ticket')
> 21 + api.fail_ticket()
>
> Just curious: what's the reason you define that function*inside* the other one ?

You always keep me honest :)

The problem I was trying to address was the fact that the "api" object
needed to be accessible to the signal handler. As the module is
currently written, I would have needed to introduce a global variable
for this. It wouldn't have been terrible, I just thought this was less
terrible.

> In practice, it often make them harder to test (you can't override them anymore).

yep. i agree.

Revision history for this message
Andy Doan (doanac) wrote :

Francis - i'm wondering if this is sufficient. I could envision a loop-hole where the lander_service_wrapper crashes do to an unforeseen bug. SIGTERM wouldn't be hit in this scenario.

I suppose we could create a jenkins job that always runs at the very end. It checks for the ticket state to be COMPLETE|FAILED, and if not FAILS it.

Maybe I'm overthinking this?

Revision history for this message
Vincent Ladeuil (vila) wrote :

>>>>> Andy Doan <email address hidden> writes:

    > On 03/09/2014 04:47 AM, Vincent Ladeuil wrote:
    >> 19 + def _on_sigterm(signame, frame):
    >> 20 + logger.error('job was terminated, failing ticket')
    >> 21 + api.fail_ticket()
    >>
    >> Just curious: what's the reason you define that function*inside* the other one ?

    > You always keep me honest :)

    > The problem I was trying to address was the fact that the "api" object
    > needed to be accessible to the signal handler. As the module is
    > currently written, I would have needed to introduce a global variable
    > for this. It wouldn't have been terrible, I just thought this was less
    > terrible.

Oh, right trickier, good enough then.

Revision history for this message
Andy Doan (doanac) wrote :

I'm going to top approve. Even if we want to do more, this change would still be perfectly fine.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lander/bin/lander_service_wrapper.py'
2--- lander/bin/lander_service_wrapper.py 2014-03-07 07:42:41 +0000
3+++ lander/bin/lander_service_wrapper.py 2014-03-09 05:22:40 +0000
4@@ -18,6 +18,7 @@
5 import json
6 import logging
7 import os
8+import signal
9 import sys
10 import time
11 import urllib2
12@@ -115,7 +116,14 @@
13
14 def _ticket_api(config):
15 master = config['master']
16- return TicketApi(master['ts_url'], master['request_id'])
17+ api = TicketApi(master['ts_url'], master['request_id'])
18+
19+ def _on_sigterm(signame, frame):
20+ logger.error('job was terminated, failing ticket')
21+ api.fail_ticket()
22+
23+ signal.signal(signal.SIGTERM, _on_sigterm)
24+ return api
25
26
27 def _get_ppa(ppa_assigner_url, ticket_id):
28
29=== modified file 'lander/bin/ticket_api.py'
30--- lander/bin/ticket_api.py 2014-03-06 23:35:46 +0000
31+++ lander/bin/ticket_api.py 2014-03-09 05:22:40 +0000
32@@ -46,6 +46,10 @@
33 resp = resp.read()
34 return json.loads(resp)
35
36+ def fail_ticket(self):
37+ url = self._url + '/updateticketstatus/' + self._ticket_id + '/'
38+ self._patch(url, {'status': TicketWorkflowStep.FAILED.value})
39+
40 def _patch_pkg_status(self, status):
41 step = TicketWorkflowStep.PKG_BUILDING.value
42 status = status.value

Subscribers

People subscribed via source and target branches