Merge lp:~barry/ubuntu-system-image/citrain301 into lp:~ubuntu-managed-branches/ubuntu-system-image/system-image
- citrain301
- Merge into system-image
Proposed by
Barry Warsaw
Status: | Merged |
---|---|
Approved by: | Barry Warsaw |
Approved revision: | 248 |
Merged at revision: | 242 |
Proposed branch: | lp:~barry/ubuntu-system-image/citrain301 |
Merge into: | lp:~ubuntu-managed-branches/ubuntu-system-image/system-image |
Diff against target: |
455 lines (+133/-69) 13 files modified
NEWS.rst (+5/-0) PKG-INFO (+1/-1) debian/changelog (+16/-0) debian/compat (+1/-1) debian/control (+10/-7) debian/tests/00_default.ini.in (+1/-1) debian/tests/control (+6/-6) setup.cfg (+1/-1) system_image.egg-info/PKG-INFO (+1/-1) systemimage/main.py (+9/-2) systemimage/testing/helpers.py (+1/-3) systemimage/tests/test_main.py (+80/-45) systemimage/version.txt (+1/-1) |
To merge this branch: | bzr merge lp:~barry/ubuntu-system-image/citrain301 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu CI managed package branches | Pending | ||
Review via email: mp+262255@code.launchpad.net |
Commit message
system-image 3.0.1
Description of the change
* New upstream release.
- LP: #1463061 - When `--progress=json` is used, print an error record
to stdout if the state machine fails.
* d/control: XS-Testsuite -> Testsuite
* d/tests
- control: Re-enable smoketests.
- 00_default.ini.in: Fix path to archive-master keyring.
To post a comment you must log in.
- 245. By Barry Warsaw
-
No change version bump for PPA wackiness
- 246. By Barry Warsaw
-
It wasn't a version problem
- 247. By Barry Warsaw
-
* d/control:
- XS-Testsuite -> Testsuite
- Bump debhelper to version 9.
- wrap-and-sort -a -t
* d/compat: Bump to version 9.
* .bzr-builddeb/default. conf: Split packaging. - 248. By Barry Warsaw
-
No split packaging
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'NEWS.rst' |
2 | --- NEWS.rst 2015-05-08 21:41:15 +0000 |
3 | +++ NEWS.rst 2015-06-18 14:03:53 +0000 |
4 | @@ -2,6 +2,11 @@ |
5 | NEWS for system-image updater |
6 | ============================= |
7 | |
8 | +3.0.1 (2015-06-16) |
9 | +================== |
10 | + * When `--progress=json` is used, print an error record to stdout if the |
11 | + state machine fails. (LP: #1463061) |
12 | + |
13 | 3.0 (2015-05-08) |
14 | ================ |
15 | * Support a built-in PyCURL-based downloader in addition to the traditional |
16 | |
17 | === modified file 'PKG-INFO' |
18 | --- PKG-INFO 2015-05-08 21:41:15 +0000 |
19 | +++ PKG-INFO 2015-06-18 14:03:53 +0000 |
20 | @@ -1,6 +1,6 @@ |
21 | Metadata-Version: 1.0 |
22 | Name: system-image |
23 | -Version: 3.0 |
24 | +Version: 3.0.1 |
25 | Summary: Ubuntu System Image Based Upgrades |
26 | Home-page: UNKNOWN |
27 | Author: Barry Warsaw |
28 | |
29 | === modified file 'debian/changelog' |
30 | --- debian/changelog 2015-05-20 15:04:21 +0000 |
31 | +++ debian/changelog 2015-06-18 14:03:53 +0000 |
32 | @@ -1,3 +1,19 @@ |
33 | +system-image (3.0.1-0ubuntu1) wily; urgency=medium |
34 | + |
35 | + * New upstream release. |
36 | + - LP: #1463061 - When `--progress=json` is used, print an error record |
37 | + to stdout if the state machine fails. |
38 | + * d/control: |
39 | + - XS-Testsuite -> Testsuite |
40 | + - Bump debhelper to version 9. |
41 | + - wrap-and-sort -a -t |
42 | + * d/compat: Bump to version 9. |
43 | + * d/tests |
44 | + - control: Re-enable smoketests. |
45 | + - 00_default.ini.in: Fix path to archive-master keyring. |
46 | + |
47 | + -- Barry Warsaw <barry@ubuntu.com> Wed, 17 Jun 2015 11:16:10 -0400 |
48 | + |
49 | system-image (3.0-0ubuntu2) wily; urgency=medium |
50 | |
51 | [ Barry Warsaw ] |
52 | |
53 | === modified file 'debian/compat' |
54 | --- debian/compat 2013-12-13 13:55:51 +0000 |
55 | +++ debian/compat 2015-06-18 14:03:53 +0000 |
56 | @@ -1,1 +1,1 @@ |
57 | -8 |
58 | +9 |
59 | |
60 | === modified file 'debian/control' |
61 | --- debian/control 2015-05-09 16:57:53 +0000 |
62 | +++ debian/control 2015-06-18 14:03:53 +0000 |
63 | @@ -6,7 +6,7 @@ |
64 | Priority: optional |
65 | Build-Depends: dbus, |
66 | dbus-x11, |
67 | - debhelper (>= 8), |
68 | + debhelper (>= 9), |
69 | dh-python, |
70 | python-docutils, |
71 | python3-all (>= 3.3), |
72 | @@ -19,9 +19,9 @@ |
73 | python3-pycurl, |
74 | python3-setuptools, |
75 | python3-xdg, |
76 | - ubuntu-download-manager |
77 | + ubuntu-download-manager, |
78 | Standards-Version: 3.9.6 |
79 | -XS-Testsuite: autopkgtest |
80 | +Testsuite: autopkgtest |
81 | Vcs-Bzr: https://code.launchpad.net/~ubuntu-managed-branches/ubuntu-system-image/system-image |
82 | Vcs-Browser: http://bazaar.launchpad.net/~ubuntu-managed-branches/ubuntu-system-image/system-image/files |
83 | X-Auto-Uploader: no-rewrite-version |
84 | @@ -30,7 +30,7 @@ |
85 | Architecture: all |
86 | Depends: system-image-common (= ${binary:Version}), |
87 | ${misc:Depends}, |
88 | - ${python3:Depends} |
89 | + ${python3:Depends}, |
90 | Description: Ubuntu system image updater command line client |
91 | This is the command line client for the Ubuntu system image updater. |
92 | |
93 | @@ -38,7 +38,7 @@ |
94 | Architecture: all |
95 | Depends: system-image-common (= ${binary:Version}), |
96 | ${misc:Depends}, |
97 | - ${python3:Depends} |
98 | + ${python3:Depends}, |
99 | Description: Ubuntu system image updater command line client |
100 | This is the command line client for the Ubuntu system image updater. |
101 | |
102 | @@ -51,13 +51,16 @@ |
103 | python3-xdg, |
104 | ubuntu-download-manager | python3-pycurl, |
105 | ${misc:Depends}, |
106 | - ${python3:Depends} |
107 | + ${python3:Depends}, |
108 | Description: Ubuntu system image updater |
109 | This is the common bits for the Ubuntu system image updater. |
110 | |
111 | Package: system-image-dev |
112 | Architecture: all |
113 | -Depends: python3-gnupg, python3-psutil, ${misc:Depends}, ${python3:Depends} |
114 | +Depends: python3-gnupg, |
115 | + python3-psutil, |
116 | + ${misc:Depends}, |
117 | + ${python3:Depends}, |
118 | Description: Ubuntu system image updater development |
119 | This is the development bits for the Ubuntu system image updater. |
120 | Install this package if you want to run the tests. |
121 | |
122 | === modified file 'debian/tests/00_default.ini.in' |
123 | --- debian/tests/00_default.ini.in 2015-05-19 20:27:26 +0000 |
124 | +++ debian/tests/00_default.ini.in 2015-06-18 14:03:53 +0000 |
125 | @@ -16,7 +16,7 @@ |
126 | settings_db: {TMPDIR}/settings.db |
127 | |
128 | [gpg] |
129 | -archive_master: /etc/system-image/archive-master.tar.xz |
130 | +archive_master: /usr/share/system-image/archive-master.tar.xz |
131 | image_master: {TMPDIR}/image-master.tar.xz |
132 | image_signing: {TMPDIR}/image-signing.tar.xz |
133 | device_signing: {TMPDIR}/device-signing.tar.xz |
134 | |
135 | === modified file 'debian/tests/control' |
136 | --- debian/tests/control 2015-05-20 14:46:42 +0000 |
137 | +++ debian/tests/control 2015-06-18 14:03:53 +0000 |
138 | @@ -1,10 +1,10 @@ |
139 | -#Tests: smoketest |
140 | -#Restrictions: isolation-container |
141 | -#Depends: system-image-common, system-image-cli, system-image-dbus, ubuntu-download-manager, dbus, dbus-x11, python3-psutil, python3-xdg, python3-pycurl |
142 | +Tests: smoketest |
143 | +Restrictions: isolation-container |
144 | +Depends: system-image-common, system-image-cli, system-image-dbus, ubuntu-download-manager, dbus, dbus-x11, python3-psutil, python3-xdg, python3-pycurl |
145 | |
146 | -#Tests: smoketest-noreboot |
147 | -#Restrictions: isolation-container allow-stderr |
148 | -#Depends: system-image-common, system-image-cli, system-image-dbus, ubuntu-download-manager, dbus, dbus-x11, python3-psutil, python3-xdg, python3-pycurl |
149 | +Tests: smoketest-noreboot |
150 | +Restrictions: isolation-container allow-stderr |
151 | +Depends: system-image-common, system-image-cli, system-image-dbus, ubuntu-download-manager, dbus, dbus-x11, python3-psutil, python3-xdg, python3-pycurl |
152 | |
153 | Tests: dryrun |
154 | Restrictions: allow-stderr |
155 | |
156 | === modified file 'setup.cfg' |
157 | --- setup.cfg 2015-05-08 21:41:15 +0000 |
158 | +++ setup.cfg 2015-06-18 14:03:53 +0000 |
159 | @@ -4,7 +4,7 @@ |
160 | logging-filter = systemimage |
161 | |
162 | [egg_info] |
163 | -tag_build = |
164 | tag_date = 0 |
165 | tag_svn_revision = 0 |
166 | +tag_build = |
167 | |
168 | |
169 | === modified file 'system_image.egg-info/PKG-INFO' |
170 | --- system_image.egg-info/PKG-INFO 2015-05-08 21:41:15 +0000 |
171 | +++ system_image.egg-info/PKG-INFO 2015-06-18 14:03:53 +0000 |
172 | @@ -1,6 +1,6 @@ |
173 | Metadata-Version: 1.0 |
174 | Name: system-image |
175 | -Version: 3.0 |
176 | +Version: 3.0.1 |
177 | Summary: Ubuntu System Image Based Upgrades |
178 | Home-page: UNKNOWN |
179 | Author: Barry Warsaw |
180 | |
181 | === modified file 'systemimage/main.py' |
182 | --- systemimage/main.py 2015-05-08 21:41:15 +0000 |
183 | +++ systemimage/main.py 2015-06-18 14:03:53 +0000 |
184 | @@ -92,7 +92,7 @@ |
185 | parser.add_argument('-C', '--config', |
186 | default=DEFAULT_CONFIG_D, action='store', |
187 | metavar='DIRECTORY', |
188 | - help="""Use the given configuration directory instead |
189 | + help="""Use the given configuration directory instead |
190 | of the default""") |
191 | parser.add_argument('-b', '--build', |
192 | default=None, action='store', |
193 | @@ -387,10 +387,17 @@ |
194 | list(state) |
195 | except KeyboardInterrupt: # pragma: no cover |
196 | return 0 |
197 | - except Exception: |
198 | + except Exception as error: |
199 | print('Exception occurred during update; see log file for details', |
200 | file=sys.stderr) |
201 | log.exception('system-image-cli exception') |
202 | + # This is a little bit of a hack because it's not generalized to |
203 | + # all values of --progress. But OTOH, we always want to log the |
204 | + # error, so --progress=logfile is redundant, and --progress=dots |
205 | + # doesn't make much sense either. Just just include some JSON |
206 | + # output if --progress=json was specified. |
207 | + if 'json' in args.progress: |
208 | + print(json.dumps(dict(type='error', msg=str(error)))) |
209 | return 1 |
210 | else: |
211 | return 0 |
212 | |
213 | === modified file 'systemimage/testing/helpers.py' |
214 | --- systemimage/testing/helpers.py 2015-05-08 21:41:15 +0000 |
215 | +++ systemimage/testing/helpers.py 2015-06-18 14:03:53 +0000 |
216 | @@ -587,9 +587,7 @@ |
217 | except: |
218 | self._resources.close() |
219 | raise |
220 | - |
221 | - def tearDown(self): |
222 | - self._resources.close() |
223 | + self.addCleanup(self._resources.close) |
224 | |
225 | def _setup_server_keyrings(self, *, device_signing=True): |
226 | # Only the archive-master key is pre-loaded. All the other keys |
227 | |
228 | === modified file 'systemimage/tests/test_main.py' |
229 | --- systemimage/tests/test_main.py 2015-05-08 21:41:15 +0000 |
230 | +++ systemimage/tests/test_main.py 2015-06-18 14:03:53 +0000 |
231 | @@ -122,10 +122,7 @@ |
232 | except: |
233 | self._resources.close() |
234 | raise |
235 | - |
236 | - def tearDown(self): |
237 | - self._resources.close() |
238 | - super().tearDown() |
239 | + self.addCleanup(self._resources.close) |
240 | |
241 | def test_config_directory_good_path(self): |
242 | # The default configuration directory exists. |
243 | @@ -1062,10 +1059,7 @@ |
244 | except: |
245 | self._resources.close() |
246 | raise |
247 | - |
248 | - def tearDown(self): |
249 | - self._resources.close() |
250 | - super().tearDown() |
251 | + self.addCleanup(self._resources.close) |
252 | |
253 | @configuration |
254 | def test_show_settings(self, config_d): |
255 | @@ -1218,12 +1212,12 @@ |
256 | class TestDBusMain(unittest.TestCase): |
257 | def setUp(self): |
258 | super().setUp() |
259 | - self._stack = ExitStack() |
260 | + self._resources = ExitStack() |
261 | try: |
262 | SystemImagePlugin.controller.set_mode() |
263 | config_d = SystemImagePlugin.controller.ini_path |
264 | override = os.path.join(config_d, '06_override.ini') |
265 | - self._stack.callback(safe_remove, override) |
266 | + self._resources.callback(safe_remove, override) |
267 | with open(override, 'w', encoding='utf-8') as fp: |
268 | print('[dbus]\nlifetime: 3s\n', file=fp) |
269 | # The testing framework will have caused system-image-dbus to be |
270 | @@ -1231,14 +1225,10 @@ |
271 | # let's be sure to stop it. |
272 | terminate_service() |
273 | except: |
274 | - self._stack.close() |
275 | + self._resources.close() |
276 | raise |
277 | - |
278 | - def tearDown(self): |
279 | - try: |
280 | - terminate_service() |
281 | - finally: |
282 | - self._stack.close() |
283 | + self.addCleanup(terminate_service) |
284 | + self.addCleanup(self._resources.close) |
285 | |
286 | def _activate(self): |
287 | # Re-start and reload the D-Bus service. |
288 | @@ -1485,39 +1475,50 @@ |
289 | CHANNEL = 'stable' |
290 | DEVICE = 'nexus7' |
291 | |
292 | + def setUp(self): |
293 | + super().setUp() |
294 | + # Use a private name to avoid conflicts with the superclass attribute. |
295 | + self.__resources = ExitStack() |
296 | + try: |
297 | + self._stdout = StringIO() |
298 | + self._stderr = StringIO() |
299 | + # Some output uses print() and others use sys.stdout.write(). Be |
300 | + # sure to capture them both to the same object. |
301 | + self.__resources.enter_context(capture_print(self._stdout)) |
302 | + self.__resources.enter_context( |
303 | + patch('systemimage.main.sys.stdout', self._stdout)) |
304 | + self.__resources.enter_context( |
305 | + patch('systemimage.main.sys.stderr', self._stderr)) |
306 | + except: |
307 | + self.__resources.close() |
308 | + raise |
309 | + self.addCleanup(self.__resources.close) |
310 | + |
311 | @configuration |
312 | def test_dots_progress(self, config_d): |
313 | # --progress=dots prints a bunch of dots to stderr. |
314 | self._setup_server_keyrings() |
315 | - stderr = StringIO() |
316 | with ExitStack() as resources: |
317 | resources.enter_context( |
318 | patch('systemimage.main.LINE_LENGTH', 10)) |
319 | resources.enter_context( |
320 | - patch('systemimage.main.sys.stderr', stderr)) |
321 | - resources.enter_context( |
322 | argv('-C', config_d, '-b', '0', '--no-reboot', |
323 | '--progress', 'dots')) |
324 | cli_main() |
325 | # There should be some dots in the stderr. |
326 | - self.assertGreater(stderr.getvalue().count('.'), 2) |
327 | + self.assertGreater(self._stderr.getvalue().count('.'), 2) |
328 | |
329 | @configuration |
330 | def test_json_progress(self, config_d): |
331 | # --progress=json prints some JSON to stdout. |
332 | self._setup_server_keyrings() |
333 | - stdout = StringIO() |
334 | - with ExitStack() as resources: |
335 | - resources.enter_context( |
336 | - patch('systemimage.main.sys.stdout', stdout)) |
337 | - resources.enter_context( |
338 | - argv('-C', config_d, '-b', '0', '--no-reboot', |
339 | - '--progress', 'json')) |
340 | + with argv('-C', config_d, '-b', '0', '--no-reboot', |
341 | + '--progress', 'json'): |
342 | cli_main() |
343 | # stdout is now filled with JSON goodness. We can't assert too much |
344 | # about the contents though. |
345 | line_count = 0 |
346 | - for line in stdout.getvalue().splitlines(): |
347 | + for line in self._stdout.getvalue().splitlines(): |
348 | line_count += 1 |
349 | record = json.loads(line) |
350 | self.assertEqual(record['type'], 'progress') |
351 | @@ -1550,8 +1551,6 @@ |
352 | def test_all_progress(self, config_d): |
353 | # We can have more than one --progress flag. |
354 | self._setup_server_keyrings() |
355 | - stdout = StringIO() |
356 | - stderr = StringIO() |
357 | log_mock = MagicMock() |
358 | from systemimage.main import _LogfileProgress |
359 | class Testable(_LogfileProgress): |
360 | @@ -1562,10 +1561,6 @@ |
361 | resources.enter_context( |
362 | patch('systemimage.main.LINE_LENGTH', 10)) |
363 | resources.enter_context( |
364 | - patch('systemimage.main.sys.stderr', stderr)) |
365 | - resources.enter_context( |
366 | - patch('systemimage.main.sys.stdout', stdout)) |
367 | - resources.enter_context( |
368 | patch('systemimage.main._LogfileProgress', Testable)) |
369 | resources.enter_context( |
370 | argv('-C', config_d, '-b', '0', '--no-reboot', |
371 | @@ -1573,9 +1568,9 @@ |
372 | '--progress', 'json', |
373 | '--progress', 'logfile')) |
374 | cli_main() |
375 | - self.assertGreater(stderr.getvalue().count('.'), 2) |
376 | + self.assertGreater(self._stderr.getvalue().count('.'), 2) |
377 | line_count = 0 |
378 | - for line in stdout.getvalue().splitlines(): |
379 | + for line in self._stdout.getvalue().splitlines(): |
380 | line_count += 1 |
381 | record = json.loads(line) |
382 | self.assertEqual(record['type'], 'progress') |
383 | @@ -1589,17 +1584,57 @@ |
384 | @configuration |
385 | def test_bad_progress(self, config_d): |
386 | # An unknown progress type results in an error. |
387 | - stderr = StringIO() |
388 | with ExitStack() as resources: |
389 | resources.enter_context( |
390 | - patch('systemimage.main.sys.stderr', stderr)) |
391 | - resources.enter_context( |
392 | argv('-C', config_d, '-b', '0', '--no-reboot', |
393 | '--progress', 'not-a-meter')) |
394 | - with self.assertRaises(SystemExit) as cm: |
395 | - cli_main() |
396 | - exit_code = cm.exception.code |
397 | - self.assertEqual(exit_code, 2) |
398 | + cm = resources.enter_context(self.assertRaises(SystemExit)) |
399 | + cli_main() |
400 | + self.assertEqual(cm.exception.code, 2) |
401 | self.assertEqual( |
402 | - stderr.getvalue().splitlines()[-1], |
403 | + self._stderr.getvalue().splitlines()[-1], |
404 | 'system-image-cli: error: Unknown progress meter: not-a-meter') |
405 | + |
406 | + @configuration |
407 | + def test_json_progress_errors(self, config): |
408 | + # When an error occurs in the state machine, --progress=json should |
409 | + # produce some client-consumable output. LP: #1463061 |
410 | + self._setup_server_keyrings() |
411 | + with ExitStack() as resources: |
412 | + resources.enter_context( |
413 | + argv('-C', config.config_d, '-b', '0', '--no-reboot', |
414 | + '--progress', 'json')) |
415 | + # It's maybe not the best thing to hook into a private |
416 | + # implementation function in order to cause the state machine to |
417 | + # fail, but it's expedient and works with both downloaders. |
418 | + resources.enter_context( |
419 | + patch('systemimage.state._copy_if_missing', |
420 | + side_effect=RuntimeError('Bad things!'))) |
421 | + exit_code = cli_main() |
422 | + self.assertEqual(exit_code, 1) |
423 | + # stdout is now filled with JSON progress. The last line should be |
424 | + # the error record. |
425 | + lines = self._stdout.getvalue().splitlines() |
426 | + record = json.loads(lines[-1]) |
427 | + self.assertEqual(record['type'], 'error', lines) |
428 | + self.assertEqual(record['msg'], 'Bad things!') |
429 | + |
430 | + @configuration |
431 | + def test_no_json_progress_errors(self, config): |
432 | + # Like above, but without --progress=json. |
433 | + self._setup_server_keyrings() |
434 | + with ExitStack() as resources: |
435 | + resources.enter_context( |
436 | + argv('-C', config.config_d, '-b', '0', '--no-reboot')) |
437 | + # It's maybe not the best thing to hook into a private |
438 | + # implementation function in order to cause the state machine to |
439 | + # fail, but it's expedient and works with both downloaders. |
440 | + resources.enter_context( |
441 | + patch('systemimage.state._copy_if_missing', |
442 | + side_effect=RuntimeError)) |
443 | + exit_code = cli_main() |
444 | + self.assertEqual(exit_code, 1) |
445 | + # stdout is now filled with JSON progress. The last line should be |
446 | + # the error record. |
447 | + lines = self._stdout.getvalue().splitlines() |
448 | + self.assertEqual(len(lines), 0) |
449 | |
450 | === modified file 'systemimage/version.txt' |
451 | --- systemimage/version.txt 2015-05-08 21:41:15 +0000 |
452 | +++ systemimage/version.txt 2015-06-18 14:03:53 +0000 |
453 | @@ -1,1 +1,1 @@ |
454 | -3.0 |
455 | +3.0.1 |