Merge lp:~doanac/uci-engine/pub-pause into lp:uci-engine

Proposed by Andy Doan
Status: Needs review
Proposed branch: lp:~doanac/uci-engine/pub-pause
Merge into: lp:uci-engine
Diff against target: 126 lines (+70/-1)
5 files modified
ci-utils/ci_utils/amqp_utils.py (+13/-0)
lander/bin/lander_process_ticket.py (+5/-0)
lander/bin/lander_service_wrapper.py (+1/-1)
lander/lander/tests/test_process_ticket.py (+19/-0)
lander/lander/tests/test_service_wrapper.py (+32/-0)
To merge this branch: bzr merge lp:~doanac/uci-engine/pub-pause
Reviewer Review Type Date Requested Status
Francis Ginther Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+223414@code.launchpad.net

Commit message

lander: allow a worker to request a 'retry'

Workers like the publisher need to mark a ticket step as needing
to be retried. This adds a function, amqp_utils.progress_retry. When
called by a worker, the lander will pause the ticket and wait until
the ticket is updated to "resume". At this point the lander will resume
execution at this step and see if it can progress

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

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

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

review: Approve (continuous-integration)
Revision history for this message
Ursula Junque (ursinha) wrote :

Hi Andy,

I've asked some questions on IRC a while ago but I think they got lost -- I should've asked them here, sorry about that.

Revision history for this message
Joe Talbott (joetalbott) wrote :

This looks okay to me code-wise. I'll leave this MP to you and Ursula to sort out as far as her comments are concerned.

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

I've responded to Ursula. I'd say we keep it the way I have it, but I'll let you guys decide.

Revision history for this message
Francis Ginther (fginther) wrote :

I think this does what it's intended to do (and there are unit tests to match). The progress_retry() isn't being used anywhere, so this shouldn't regress anything.

Only question is if the name 'progress_retry' was meant to be named 'progress_pause'?

I'll approve as we really can't do much more with it until something else is in place to exercise it.

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

On Thu, Jul 17, 2014 at 10:32 PM, Francis Ginther <
<email address hidden>> wrote:

> > +def progress_retry(progress_trigger, data=None):
> > + '''Let the engine know the ticket should be paused and retried
> after some
> > + manual acknowledgement has taken place
> > + '''
> > + if data is None:
> > + data = {}
> > + data['state'] = 'RETRY'
>
> It sounds a bit odd to have this method called 'progress_retry' when the
> outcome is to pause the workflow. I think this is what Ursula is pointing
> out.
>

Ah - i get it now. So "retry" in this since is still a manual thing that
takes advantage of our internal "pause" support. ie - the way the step
would get repeated would be for some interaction that puts the ticket
status into "continue"

Unmerged revisions

589. By Andy Doan

lander: allow a worker to request a 'retry'

Workers like the publisher need to mark a ticket step as needing
to be retried. This adds a function, amqp_utils.progress_retry. When
called by a worker, the lander will pause the ticket and wait until
the ticket is updated to "resume". At this point the lander will resume
execution at this step and see if it can progress

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ci-utils/ci_utils/amqp_utils.py'
2--- ci-utils/ci_utils/amqp_utils.py 2014-06-16 13:18:53 +0000
3+++ ci-utils/ci_utils/amqp_utils.py 2014-06-17 14:51:54 +0000
4@@ -199,3 +199,16 @@
5 data['result'] = 'FAILED'
6 data['exit'] = True
7 return send(progress_trigger, json.dumps(data))
8+
9+
10+def progress_retry(progress_trigger, data=None):
11+ '''Let the engine know the ticket should be paused and retried after some
12+ manual acknowledgement has taken place
13+ '''
14+ if data is None:
15+ data = {}
16+ data['state'] = 'RETRY'
17+ data['result'] = 'PASSED'
18+ data['pause'] = {}
19+ data['exit'] = True
20+ return send(progress_trigger, json.dumps(data))
21
22=== modified file 'lander/bin/lander_process_ticket.py'
23--- lander/bin/lander_process_ticket.py 2014-06-16 13:18:53 +0000
24+++ lander/bin/lander_process_ticket.py 2014-06-17 14:51:54 +0000
25@@ -34,6 +34,11 @@
26 rc = subprocess.call(
27 [cmd, '--service', step['name'], '--results-file', results_file])
28 logger.debug('Step completed with rc=%d', rc)
29+
30+ # load the result to see if the step requested a "retry", which means
31+ # we are basically pausing this step
32+ wflow = workflow.load(results_file)
33+ _handle_pause(results_file, wflow, wflow.get_step(step['name']))
34 return rc
35
36
37
38=== modified file 'lander/bin/lander_service_wrapper.py'
39--- lander/bin/lander_service_wrapper.py 2014-06-11 19:16:37 +0000
40+++ lander/bin/lander_service_wrapper.py 2014-06-17 14:51:54 +0000
41@@ -68,7 +68,6 @@
42 if state == 'STATUS':
43 self.started_cb()
44 elif state == 'COMPLETED':
45- self.ticket.process_artifacts(data)
46 if data['result'] == 'PASSED':
47 self.completed_cb(True)
48 else:
49@@ -76,6 +75,7 @@
50
51 msg.channel.basic_ack(msg.delivery_tag)
52 if data.get('exit'):
53+ self.ticket.process_artifacts(data)
54 self.data = data
55 # this will kick us out of the run-forever worker loop
56 msg.channel.basic_cancel(msg.consumer_tag)
57
58=== modified file 'lander/lander/tests/test_process_ticket.py'
59--- lander/lander/tests/test_process_ticket.py 2014-06-10 16:21:15 +0000
60+++ lander/lander/tests/test_process_ticket.py 2014-06-17 14:51:54 +0000
61@@ -116,3 +116,22 @@
62 lander_process_ticket.main(args)
63 self.assertEqual(1, do_step.call_count)
64 self.assertEqual(1, ticket_api.TicketApi().pause_ticket.call_count)
65+
66+ @mock.patch('lander.ticket_api')
67+ @mock.patch('subprocess.call')
68+ def test_run_retry(self, subprocess, ticket_api):
69+ subprocess.return_value = 0
70+ data = {
71+ 'ticket_id': 10,
72+ 'ts_url': 'foo',
73+ 'steps': [
74+ {'name': 'step1', 'pause': {}},
75+ ],
76+ }
77+ wflow = workflow._Workflow(data)
78+ with open(self.tmpfile, 'w') as f:
79+ wflow.save(f)
80+ with self.assertRaises(SystemExit):
81+ step = wflow.get_step('step1')
82+ lander_process_ticket._do_step(step, self.tmpfile)
83+ self.assertEqual(1, ticket_api.TicketApi().pause_ticket.call_count)
84
85=== modified file 'lander/lander/tests/test_service_wrapper.py'
86--- lander/lander/tests/test_service_wrapper.py 2014-06-10 16:21:15 +0000
87+++ lander/lander/tests/test_service_wrapper.py 2014-06-17 14:51:54 +0000
88@@ -432,6 +432,38 @@
89 self.assertEqual('FAILED', data['result'])
90 self.assertEqual(err_msg, data['error'])
91
92+ @mock.patch('lander.ticket_api.TicketApi')
93+ @mock.patch('ci_utils.amqp_utils.send')
94+ @mock.patch('ci_utils.amqp_utils.connection')
95+ def testRunnerRetry(self, connection, send, api):
96+ '''Ensure we generate the proper response if we get a retry msg.'''
97+ api().get_full_ticket.return_value = {}
98+ # mock the run-forever logic to ensure we return what we expect
99+ state = {'state': 'RETRY', 'result': 'PASSED',
100+ 'foo': 'bar', 'exit': True, 'name': 'test_runner'}
101+
102+ def amqp():
103+ def run_forever(channel, queue, callback):
104+ m = mock.Mock()
105+ m.body = json.dumps({'state': 'WAITING'})
106+ callback(m)
107+ m.body = json.dumps(state)
108+ callback(m)
109+ return run_forever
110+
111+ args = self.base_args + ['--service', 'test_runner']
112+ args = lander_service_wrapper._get_parser().parse_args(args)
113+
114+ with mock.patch('ci_utils.amqp_utils._run_forever', new_callable=amqp):
115+ rc = lander_service_wrapper.main(args)
116+ self.assertEqual(0, rc)
117+
118+ api().set_testing_waiting.assert_called_once()
119+ self.assertEqual(0, api().set_testing_complete.call_count)
120+
121+ data = lander.workflow.load(self.results).get_step('test_runner')
122+ self.assertEqual(state, data)
123+
124 @mock.patch('lander_service_wrapper._patch')
125 def testPPAFreeSucceeds(self, patch):
126 '''ensure we can free a PPA'''

Subscribers

People subscribed via source and target branches