Merge lp:~juliank/update-notifier/esm into lp:update-notifier

Proposed by Julian Andres Klode on 2019-03-29
Status: Merged
Merged at revision: 958
Proposed branch: lp:~juliank/update-notifier/esm
Merge into: lp:update-notifier
Diff against target: 339 lines (+243/-7)
4 files modified
data/apt_check.py (+97/-7)
debian/changelog (+7/-0)
debian/rules (+2/-0)
tests/test_motd.py (+137/-0)
To merge this branch: bzr merge lp:~juliank/update-notifier/esm
Reviewer Review Type Date Requested Status
Ubuntu Core Development Team 2019-03-29 Pending
Review via email: mp+365288@code.launchpad.net
To post a comment you must log in.
Brian Murray (brian-murray) wrote :

Nothing critical but a few comments appear in-line.

Joshua Powers (powersj) wrote :

one in-line

Patricia Gaughen (gaughen) :
lp:~juliank/update-notifier/esm updated on 2019-04-01
960. By Julian Andres Klode on 2019-04-01

apt-check: Count enabled ESM upgrades

Brian Murray (brian-murray) wrote :

A few more comments, thanks for addressing the other ones.

lp:~juliank/update-notifier/esm updated on 2019-04-02
961. By Julian Andres Klode on 2019-04-02

apt-check: Tell people to enable ESM if ESM updates are available

962. By Julian Andres Klode on 2019-04-02

Add changelog entry and test case

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/apt_check.py'
2--- data/apt_check.py 2018-11-13 20:53:28 +0000
3+++ data/apt_check.py 2019-04-02 13:17:38 +0000
4@@ -45,6 +45,7 @@
5 def isSecurityUpgrade(ver):
6 " check if the given version is a security update (or masks one) "
7 security_pockets = [("Ubuntu", "%s-security" % DISTRO),
8+ ("UbuntuESM", "%s-security" % DISTRO),
9 ("gNewSense", "%s-security" % DISTRO),
10 ("Debian", "%s-updates" % DISTRO)]
11 for (file, index) in ver.file_list:
12@@ -54,6 +55,14 @@
13 return False
14
15
16+def isESMUpgrade(ver):
17+ " check if the given version is a security update (or masks one) "
18+ for (file, index) in ver.file_list:
19+ if file.origin == "UbuntuESM" and file.archive.startswith(DISTRO):
20+ return True
21+ return False
22+
23+
24 def write_package_names(outstream, cache, depcache):
25 " write out package names that change to outstream "
26 pkgs = [pkg for pkg in cache.packages if depcache.marked_install(pkg)
27@@ -61,19 +70,77 @@
28 outstream.write("\n".join([p.name for p in pkgs]))
29
30
31-def write_human_readable_summary(outstream, upgrades, security_updates):
32+def write_human_readable_summary(outstream, upgrades, security_updates,
33+ esm_updates, have_esm, disabled_esm_updates):
34 " write out human summary summary to outstream "
35+ if have_esm is not None:
36+ if have_esm:
37+ outstream.write(gettext.dgettext("update-notifier",
38+ "Extended Security Maintenance "
39+ "(ESM) is enabled."))
40+ else:
41+ outstream.write(gettext.dgettext("update-notifier",
42+ "Extended Security Maintenance "
43+ "(ESM) is not enabled."))
44+ outstream.write("\n\n")
45+
46 outstream.write(gettext.dngettext("update-notifier",
47- "%i package can be updated.",
48- "%i packages can be updated.",
49+ "%i update can be installed "
50+ "immediately.",
51+ "%i updates can be installed "
52+ "immediately.",
53 upgrades) % upgrades)
54 outstream.write("\n")
55+ if esm_updates > 0:
56+ outstream.write(gettext.dngettext("update-notifier",
57+ "%i of these updates is "
58+ "provided through ESM.",
59+ "%i of these updates are "
60+ "provided through ESM.",
61+ esm_updates) %
62+ esm_updates)
63+ outstream.write("\n")
64 outstream.write(gettext.dngettext("update-notifier",
65- "%i update is a security update.",
66- "%i updates are security updates.",
67- security_updates) % security_updates)
68+ "%i of these updates is a "
69+ "security update.",
70+ "%i of these updates are "
71+ "security updates.",
72+ security_updates) %
73+ security_updates)
74 outstream.write("\n")
75
76+ if disabled_esm_updates > 0:
77+ outstream.write("\n")
78+ outstream.write(gettext.dngettext("update-notifier",
79+ "Enable ESM to receive %i additional "
80+ "security update.",
81+ "Enable ESM to receive %i additional "
82+ "security updates.",
83+ disabled_esm_updates) %
84+ disabled_esm_updates)
85+ outstream.write("\n")
86+ outstream.write(gettext.dgettext("update-notifier",
87+ "See 'ua enable esm' or "
88+ "https://ubuntu.com/esm"))
89+ outstream.write("\n")
90+
91+
92+def has_disabled_esm_security_update(depcache, pkg):
93+ " check if we have a disabled ESM security update "
94+ inst_ver = pkg.current_ver
95+ if not inst_ver:
96+ return False
97+
98+ for ver in pkg.version_list:
99+ if ver == inst_ver:
100+ break
101+
102+ for (file, index) in ver.file_list:
103+ if (file.origin == "UbuntuESM" and file.archive.startswith(DISTRO)
104+ and depcache.policy.get_priority(file) == -32768):
105+ return True
106+ return False
107+
108
109 def init():
110 " init the system, be nice "
111@@ -115,13 +182,30 @@
112 sys.stderr.write("E: " + _("Error: Marking the upgrade (%s)") % e)
113 sys.exit(-1)
114
115+ # Check if we have ESM enabled or disabled; and if it exists in the
116+ # first place.
117+ have_esm = None # None == does not exist
118+ for file in cache.file_list:
119+ if file.origin == "UbuntuESM" and file.archive.startswith(DISTRO):
120+ # In case of multiple ESM repos, one enabled is sufficient.
121+ if have_esm is None and depcache.policy.get_priority(file) == -32768:
122+ have_esm = False
123+ else:
124+ have_esm = True
125+ break
126+
127 # analyze the ugprade
128 upgrades = 0
129 security_updates = 0
130+ esm_updates = 0
131+ disabled_esm_updates = 0
132
133 # we need another cache that has more pkg details
134 with apt.Cache() as aptcache:
135 for pkg in cache.packages:
136+ if has_disabled_esm_security_update(depcache, pkg):
137+ disabled_esm_updates += 1
138+
139 # skip packages that are not marked upgraded/installed
140 if not (depcache.marked_install(pkg)
141 or depcache.marked_upgrade(pkg)):
142@@ -134,6 +218,8 @@
143 continue
144 # check for security upgrades
145 if isSecurityUpgrade(cand_ver):
146+ if isESMUpgrade(cand_ver):
147+ esm_updates += 1
148 upgrades += 1
149 security_updates += 1
150 continue
151@@ -159,6 +245,8 @@
152 and apt_pkg.version_compare(ver.ver_str,
153 inst_ver.ver_str) <= 0):
154 continue
155+ if isESMUpgrade(ver):
156+ esm_updates += 1
157 if isSecurityUpgrade(ver):
158 security_updates += 1
159 break
160@@ -167,7 +255,9 @@
161 if options and options.show_package_names:
162 write_package_names(sys.stderr, cache, depcache)
163 elif options and options.readable_output:
164- write_human_readable_summary(sys.stdout, upgrades, security_updates)
165+ write_human_readable_summary(sys.stdout, upgrades, security_updates,
166+ esm_updates, have_esm,
167+ disabled_esm_updates)
168 else:
169 # print the number of regular upgrades and the number of
170 # security upgrades
171
172=== modified file 'debian/changelog'
173--- debian/changelog 2019-03-19 10:27:07 +0000
174+++ debian/changelog 2019-04-02 13:17:38 +0000
175@@ -1,3 +1,10 @@
176+update-notifier (3.192.16) UNRELEASED; urgency=medium
177+
178+ * Rewrite and extend motd messaging (LP: #1822340)
179+ * Count ESM security updates as security updates
180+
181+ -- Julian Andres Klode <juliank@ubuntu.com> Fri, 29 Mar 2019 16:26:45 +0100
182+
183 update-notifier (3.192.15) disco; urgency=medium
184
185 * debian/control:
186
187=== modified file 'debian/rules'
188--- debian/rules 2018-05-09 10:59:08 +0000
189+++ debian/rules 2019-04-02 13:17:38 +0000
190@@ -13,3 +13,5 @@
191
192 override_dh_auto_test:
193 cd tests && python3 test_package-data-downloader.py
194+ cd tests && python3 test_motd.py
195+
196
197=== added symlink 'tests/apt_check.py'
198=== target is u'../data/apt_check.py'
199=== added file 'tests/test_motd.py'
200--- tests/test_motd.py 1970-01-01 00:00:00 +0000
201+++ tests/test_motd.py 2019-04-02 13:17:38 +0000
202@@ -0,0 +1,137 @@
203+#!/usr/bin/python3
204+# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
205+
206+import apt_check
207+import io
208+import os
209+import subprocess
210+import unittest
211+import textwrap
212+
213+
214+def get_message(*args, **kwds):
215+ with io.StringIO() as stream:
216+ apt_check.write_human_readable_summary(stream, *args, **kwds)
217+ return stream.getvalue()
218+
219+
220+class TestMotd(unittest.TestCase):
221+ """ ensure that the tree is pep8 clean """
222+
223+ def test_esm_disabled_upto_date_esm_avail(self):
224+ self.assertEqual(
225+ get_message(upgrades=0, security_updates=0,
226+ esm_updates=0, have_esm=False,
227+ disabled_esm_updates=23),
228+ textwrap.dedent(
229+ """
230+ Extended Security Maintenance (ESM) is not enabled.
231+
232+ 0 updates can be installed immediately.
233+ 0 of these updates are security updates.
234+
235+ Enable ESM to receive 23 additional security updates.
236+ See 'ua enable esm' or https://ubuntu.com/esm
237+ """).lstrip())
238+
239+ def test_esm_disabled_security_esm_avail(self):
240+ self.assertEqual(
241+ get_message(upgrades=15, security_updates=7,
242+ esm_updates=0, have_esm=False,
243+ disabled_esm_updates=23),
244+ textwrap.dedent(
245+ """
246+ Extended Security Maintenance (ESM) is not enabled.
247+
248+ 15 updates can be installed immediately.
249+ 7 of these updates are security updates.
250+
251+ Enable ESM to receive 23 additional security updates.
252+ See 'ua enable esm' or https://ubuntu.com/esm
253+ """).lstrip())
254+
255+ def test_esm_disabled_security_no_esm_avail(self):
256+ self.assertEqual(
257+ get_message(upgrades=15, security_updates=7,
258+ esm_updates=0, have_esm=False,
259+ disabled_esm_updates=0),
260+ textwrap.dedent(
261+ """
262+ Extended Security Maintenance (ESM) is not enabled.
263+
264+ 15 updates can be installed immediately.
265+ 7 of these updates are security updates.
266+ """).lstrip())
267+
268+ def test_esm_disabled_nosecurity(self):
269+ self.assertEqual(
270+ get_message(upgrades=15, security_updates=0,
271+ esm_updates=0, have_esm=False,
272+ disabled_esm_updates=0),
273+ textwrap.dedent(
274+ """
275+ Extended Security Maintenance (ESM) is not enabled.
276+
277+ 15 updates can be installed immediately.
278+ 0 of these updates are security updates.
279+ """).lstrip())
280+
281+ def test_esm_disabled_noupdates(self):
282+ self.assertEqual(
283+ get_message(upgrades=0, security_updates=0,
284+ esm_updates=0, have_esm=False,
285+ disabled_esm_updates=0),
286+ textwrap.dedent(
287+ """
288+ Extended Security Maintenance (ESM) is not enabled.
289+
290+ 0 updates can be installed immediately.
291+ 0 of these updates are security updates.
292+ """).lstrip())
293+
294+ def test_esm_enabled_nosecurity(self):
295+ self.assertEqual(
296+ get_message(upgrades=35, security_updates=0,
297+ esm_updates=13, have_esm=True,
298+ disabled_esm_updates=0),
299+ textwrap.dedent(
300+ """
301+ Extended Security Maintenance (ESM) is enabled.
302+
303+ 35 updates can be installed immediately.
304+ 13 of these updates are provided through ESM.
305+ 0 of these updates are security updates.
306+ """).lstrip())
307+
308+ def test_esm_enabled_somesecurity(self):
309+ self.assertEqual(
310+ get_message(upgrades=47, security_updates=7,
311+ esm_updates=13, have_esm=True,
312+ disabled_esm_updates=0),
313+ textwrap.dedent(
314+ """
315+ Extended Security Maintenance (ESM) is enabled.
316+
317+ 47 updates can be installed immediately.
318+ 13 of these updates are provided through ESM.
319+ 7 of these updates are security updates.
320+ """).lstrip())
321+
322+ def test_esm_enabled_noupdates(self):
323+ self.assertEqual(
324+ get_message(upgrades=0, security_updates=0,
325+ esm_updates=0, have_esm=True,
326+ disabled_esm_updates=0),
327+ textwrap.dedent(
328+ """
329+ Extended Security Maintenance (ESM) is enabled.
330+
331+ 0 updates can be installed immediately.
332+ 0 of these updates are security updates.
333+ """).lstrip())
334+
335+
336+if __name__ == "__main__":
337+ import logging
338+ logging.basicConfig(level=logging.DEBUG)
339+ unittest.main()

Subscribers

People subscribed via source and target branches

to all changes: