Merge lp:~frankban/charms/precise/juju-gui/bug-1132905-log-hook into lp:~juju-gui/charms/precise/juju-gui/trunk

Proposed by Francesco Banconi
Status: Merged
Merged at revision: 32
Proposed branch: lp:~frankban/charms/precise/juju-gui/bug-1132905-log-hook
Merge into: lp:~juju-gui/charms/precise/juju-gui/trunk
Diff against target: 285 lines (+83/-41)
6 files modified
hooks/config-changed (+2/-11)
hooks/install (+4/-14)
hooks/start (+2/-6)
hooks/stop (+6/-10)
hooks/utils.py (+23/-0)
tests/test_utils.py (+46/-0)
To merge this branch: bzr merge lp:~frankban/charms/precise/juju-gui/bug-1132905-log-hook
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+150413@code.launchpad.net

Description of the change

Add and use a log_hook context manager.

Replace the current calls to log_entry and log_exit in the __main__ of
the hooks with a log_hook context manager, simplifying the code a bit.

Avoiding log_entry and log_exit also temporarily works around a problem
they have with the juju-core handling of strings starting with "--" in
juju-log.

https://codereview.appspot.com/7379050/

To post a comment you must log in.
Revision history for this message
Francesco Banconi (frankban) wrote :

Reviewers: mp+150413_code.launchpad.net,

Message:
Please take a look.

Description:
Add and use a log_hook context manager.

Replace the current calls to log_entry and log_exit in the __main__ of
the hooks with a log_hook context manager, simplifying the code a bit.

Avoiding log_entry and log_exit also temporarily works around a problem
they have with the juju-core handling of strings starting with "--" in
juju-log.

https://code.launchpad.net/~frankban/charms/precise/juju-gui/bug-1132905-log-hook/+merge/150413

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/7379050/

Affected files:
   A [revision details]
   M hooks/config-changed
   M hooks/install
   M hooks/start
   M hooks/stop
   M hooks/utils.py
   M tests/test_utils.py

Revision history for this message
Gary Poster (gary) wrote :
Revision history for this message
Francesco Banconi (frankban) wrote :

*** Submitted:

Add and use a log_hook context manager.

Replace the current calls to log_entry and log_exit in the __main__ of
the hooks with a log_hook context manager, simplifying the code a bit.

Avoiding log_entry and log_exit also temporarily works around a problem
they have with the juju-core handling of strings starting with "--" in
juju-log.

R=gary.poster
CC=
https://codereview.appspot.com/7379050

https://codereview.appspot.com/7379050/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hooks/config-changed'
2--- hooks/config-changed 2013-02-04 18:05:31 +0000
3+++ hooks/config-changed 2013-02-25 19:12:24 +0000
4@@ -4,14 +4,11 @@
5 # Copyright 2012 Canonical Ltd. This software is licensed under the
6 # GNU Affero General Public License version 3 (see the file LICENSE).
7
8-from subprocess import CalledProcessError
9 import sys
10
11 from charmhelpers import (
12 get_config,
13 log,
14- log_entry,
15- log_exit,
16 service_control,
17 STOP,
18 )
19@@ -27,6 +24,7 @@
20 fetch_gui,
21 HAPROXY,
22 IMPROV,
23+ log_hook,
24 NGINX,
25 save_or_create_certificates,
26 setup_gui,
27@@ -134,12 +132,5 @@
28
29
30 if __name__ == '__main__':
31- log_entry()
32- try:
33+ with log_hook():
34 main()
35- except CalledProcessError as e:
36- log('Exception caught:')
37- log(e.output)
38- raise
39- finally:
40- log_exit()
41
42=== modified file 'hooks/install'
43--- hooks/install 2013-02-06 08:46:56 +0000
44+++ hooks/install 2013-02-25 19:12:24 +0000
45@@ -3,10 +3,8 @@
46
47 import os
48 import shutil
49-from subprocess import (
50- CalledProcessError,
51- check_call,
52-)
53+from subprocess import check_call
54+
55
56 # If the user's environment has "juju-origin: ppa" set, they will
57 # automatically have access to python-charmhelpers and python-shelltoolbox.
58@@ -30,8 +28,6 @@
59 from charmhelpers import (
60 get_config,
61 log,
62- log_entry,
63- log_exit,
64 )
65 from shelltoolbox import (
66 apt_get_install,
67@@ -43,6 +39,7 @@
68 config_json,
69 fetch_api,
70 fetch_gui,
71+ log_hook,
72 save_or_create_certificates,
73 setup_gui,
74 setup_nginx,
75@@ -88,12 +85,5 @@
76
77
78 if __name__ == '__main__':
79- log_entry()
80- try:
81+ with log_hook():
82 main()
83- except CalledProcessError as e:
84- log('Exception caught:')
85- log(e.output)
86- raise
87- finally:
88- log_exit()
89
90=== modified file 'hooks/start'
91--- hooks/start 2013-02-04 18:05:31 +0000
92+++ hooks/start 2013-02-25 19:12:24 +0000
93@@ -4,12 +4,11 @@
94 from charmhelpers import (
95 get_config,
96 log,
97- log_entry,
98- log_exit,
99 open_port,
100 )
101
102 from utils import (
103+ log_hook,
104 start_agent,
105 start_gui,
106 start_improv,
107@@ -38,8 +37,5 @@
108
109
110 if __name__ == '__main__':
111- log_entry()
112- try:
113+ with log_hook():
114 main()
115- finally:
116- log_exit()
117
118=== modified file 'hooks/stop'
119--- hooks/stop 2012-12-19 09:57:45 +0000
120+++ hooks/stop 2013-02-25 19:12:24 +0000
121@@ -1,14 +1,13 @@
122 #!/usr/bin/env python2
123 #-*- python -*-
124
125-from charmhelpers import (
126- get_config,
127- log_entry,
128- log_exit,
129+from charmhelpers import get_config
130+
131+from utils import (
132+ log_hook,
133+ stop,
134 )
135
136-from utils import stop
137-
138
139 def main():
140 config = get_config()
141@@ -16,8 +15,5 @@
142
143
144 if __name__ == '__main__':
145- log_entry()
146- try:
147+ with log_hook():
148 main()
149- finally:
150- log_exit()
151
152=== modified file 'hooks/utils.py'
153--- hooks/utils.py 2013-02-05 18:02:27 +0000
154+++ hooks/utils.py 2013-02-25 19:12:24 +0000
155@@ -17,6 +17,7 @@
156 'JUJU_GUI_DIR',
157 'JUJU_GUI_SITE',
158 'JUJU_PEM',
159+ 'log_hook',
160 'NGINX',
161 'parse_source',
162 'render_to_file',
163@@ -30,10 +31,12 @@
164 'WEB_PORT',
165 ]
166
167+from contextlib import contextmanager
168 import json
169 import os
170 import logging
171 import shutil
172+from subprocess import CalledProcessError
173 import tempfile
174 import tempita
175
176@@ -42,6 +45,7 @@
177 command,
178 environ,
179 run,
180+ script_name,
181 search_file,
182 Serializer,
183 su,
184@@ -132,6 +136,25 @@
185 return line.split('=')[1].strip('"')
186
187
188+@contextmanager
189+def log_hook():
190+ """Log when an hook starts and stops its execution.
191+
192+ Also log to stdout possible CalledProcessError exceptions raised executing
193+ the hook.
194+ """
195+ script = script_name()
196+ log(">>> Entering {}".format(script))
197+ try:
198+ yield
199+ except CalledProcessError as err:
200+ log('Exception caught:')
201+ log(err.output)
202+ raise
203+ finally:
204+ log("<<< Exiting {}".format(script))
205+
206+
207 def parse_source(source):
208 """Parse the ``juju-gui-source`` option.
209
210
211=== modified file 'tests/test_utils.py'
212--- tests/test_utils.py 2013-02-05 17:52:22 +0000
213+++ tests/test_utils.py 2013-02-25 19:12:24 +0000
214@@ -4,11 +4,13 @@
215 import os
216 import shutil
217 from simplejson import dumps
218+from subprocess import CalledProcessError
219 import tempfile
220 import tempita
221 import unittest
222
223 import charmhelpers
224+
225 from utils import (
226 _get_by_attr,
227 API_PORT,
228@@ -18,6 +20,7 @@
229 get_zookeeper_address,
230 JUJU_GUI_DIR,
231 JUJU_PEM,
232+ log_hook,
233 parse_source,
234 render_to_file,
235 save_or_create_certificates,
236@@ -266,6 +269,49 @@
237 self.assertEqual(self.zookeeper_address, address)
238
239
240+class LogHookTest(unittest.TestCase):
241+
242+ def setUp(self):
243+ # Monkeypatch the charmhelpers log function.
244+ self.output = []
245+ self.original = utils.log
246+ utils.log = self.output.append
247+
248+ def tearDown(self):
249+ # Restore the original charmhelpers log function.
250+ utils.log = self.original
251+
252+ def test_logging(self):
253+ # The function emits log messages on entering and exiting the hook.
254+ with log_hook():
255+ self.output.append('executing hook')
256+ self.assertEqual(3, len(self.output))
257+ enter_message, executing_message, exit_message = self.output
258+ self.assertIn('>>> Entering', enter_message)
259+ self.assertEqual('executing hook', executing_message)
260+ self.assertIn('<<< Exiting', exit_message)
261+
262+ def test_subprocess_error(self):
263+ # If a CalledProcessError exception is raised, the command output is
264+ # logged.
265+ with self.assertRaises(CalledProcessError) as cm:
266+ with log_hook():
267+ raise CalledProcessError(2, 'command', 'output')
268+ exception = cm.exception
269+ self.assertIsInstance(exception, CalledProcessError)
270+ self.assertEqual(2, exception.returncode)
271+ self.assertEqual('output', self.output[-2])
272+
273+ def test_error(self):
274+ # Possible errors are re-raised by the context manager.
275+ with self.assertRaises(TypeError) as cm:
276+ with log_hook():
277+ raise TypeError
278+ exception = cm.exception
279+ self.assertIsInstance(exception, TypeError)
280+ self.assertIn('<<< Exiting', self.output[-1])
281+
282+
283 class ParseSourceTest(unittest.TestCase):
284
285 def test_latest_stable_release(self):

Subscribers

People subscribed via source and target branches