Merge lp:~barry/ubuntu-system-image/citrain301 into lp:~ubuntu-managed-branches/ubuntu-system-image/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
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

Subscribers

People subscribed via source and target branches