Merge ~dbungert/curtin:command-apt-libapt-v4 into curtin:master
- Git
- lp:~dbungert/curtin
- command-apt-libapt-v4
- Merge into master
Status: | Merged |
---|---|
Approved by: | Dan Bungert |
Approved revision: | 7193cf40c5f65bd52d615eb19199d2e468f13030 |
Merge reported by: | Server Team CI bot |
Merged at revision: | not available |
Proposed branch: | ~dbungert/curtin:command-apt-libapt-v4 |
Merge into: | curtin:master |
Diff against target: |
530 lines (+195/-112) 5 files modified
curtin/commands/apt_config.py (+68/-59) tests/unittests/test_apt_source.py (+113/-50) tests/vmtests/__init__.py (+11/-0) tests/vmtests/test_apt_source.py (+2/-3) tox.ini (+1/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Michael Hudson-Doyle | Approve | ||
Review via email: mp+408383@code.launchpad.net |
Commit message
commands/apt: use python-apt for sources.list
Start using python{,3}-apt for sources.list handling.
generate_
stage performs one specific transformation on the list of entries.
Description of the change
Server Team CI bot (server-team-bot) wrote : | # |
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:7d32d97412f
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:17251758df3
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 0cf5057... by Dan Bungert
-
tox: +sitepackages for py27-pylint
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:0cf505757ae
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Michael Hudson-Doyle (mwhudson) wrote : | # |
Very nice. Just one suggestion, feel free to act on or ignore that and then merge, no further review required.
- 7193cf4... by Dan Bungert
-
commands/apt: uri update simplification
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:7193cf40c5f
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | diff --git a/curtin/commands/apt_config.py b/curtin/commands/apt_config.py |
2 | index e7d84c0..ef4a34c 100644 |
3 | --- a/curtin/commands/apt_config.py |
4 | +++ b/curtin/commands/apt_config.py |
5 | @@ -11,6 +11,8 @@ import os |
6 | import re |
7 | import sys |
8 | |
9 | +from aptsources.sourceslist import SourceEntry |
10 | + |
11 | from curtin.log import LOG |
12 | from curtin import (config, distro, gpg, paths, util) |
13 | |
14 | @@ -211,22 +213,38 @@ def rename_apt_lists(new_mirrors, target=None): |
15 | LOG.warn("Failed to rename apt list:", exc_info=True) |
16 | |
17 | |
18 | -def mirror_to_placeholder(tmpl, mirror, placeholder): |
19 | - """ mirror_to_placeholder |
20 | - replace the specified mirror in a template with a placeholder string |
21 | - Checks for existance of the expected mirror and warns if not found |
22 | - """ |
23 | - if mirror not in tmpl: |
24 | - if mirror.endswith("/") and mirror[:-1] in tmpl: |
25 | - LOG.debug("mirror_to_placeholder: '%s' did not exist in tmpl, " |
26 | - "did without a trailing /. Accomodating.", mirror) |
27 | - mirror = mirror[:-1] |
28 | - else: |
29 | - LOG.warn("Expected mirror '%s' not found in: %s", mirror, tmpl) |
30 | - return tmpl.replace(mirror, placeholder) |
31 | +def update_default_mirrors(entries, mirrors, target): |
32 | + """replace existing default repos with the configured mirror""" |
33 | + |
34 | + defaults = get_default_mirrors(distro.get_architecture(target)) |
35 | + mirrors_replacement = { |
36 | + defaults['PRIMARY']: mirrors["MIRROR"], |
37 | + defaults['SECURITY']: mirrors["SECURITY"], |
38 | + } |
39 | + |
40 | + # allow original file URIs without the trailing slash to match mirror |
41 | + # specifications that have it |
42 | + noslash = {} |
43 | + for key in mirrors_replacement.keys(): |
44 | + if key[-1] == '/': |
45 | + noslash[key[:-1]] = mirrors_replacement[key] |
46 | + |
47 | + mirrors_replacement.update(noslash) |
48 | + |
49 | + for entry in entries: |
50 | + entry.uri = mirrors_replacement.get(entry.uri, entry.uri) |
51 | + return entries |
52 | + |
53 | |
54 | +def update_mirrors(entries, mirrors): |
55 | + """perform template replacement of mirror placeholders with configured |
56 | + values""" |
57 | + for entry in entries: |
58 | + entry.uri = util.render_string(entry.uri, mirrors) |
59 | + return entries |
60 | |
61 | -def map_known_suites(suite): |
62 | + |
63 | +def map_known_suites(suite, release): |
64 | """there are a few default names which will be auto-extended. |
65 | This comes at the inability to use those names literally as suites, |
66 | but on the other hand increases readability of the cfg quite a lot""" |
67 | @@ -236,10 +254,10 @@ def map_known_suites(suite): |
68 | 'proposed': '$RELEASE-proposed', |
69 | 'release': '$RELEASE'} |
70 | try: |
71 | - retsuite = mapping[suite] |
72 | + template_suite = mapping[suite] |
73 | except KeyError: |
74 | - retsuite = suite |
75 | - return retsuite |
76 | + template_suite = suite |
77 | + return util.render_string(template_suite, {'RELEASE': release}) |
78 | |
79 | |
80 | def disable_suites(disabled, src, release): |
81 | @@ -248,36 +266,30 @@ def disable_suites(disabled, src, release): |
82 | if not disabled: |
83 | return src |
84 | |
85 | - retsrc = src |
86 | + suites_to_disable = [] |
87 | for suite in disabled: |
88 | - suite = map_known_suites(suite) |
89 | - releasesuite = util.render_string(suite, {'RELEASE': release}) |
90 | - LOG.debug("Disabling suite %s as %s", suite, releasesuite) |
91 | + release_suite = map_known_suites(suite, release) |
92 | + LOG.debug("Disabling suite %s as %s", suite, release_suite) |
93 | + suites_to_disable.append(release_suite) |
94 | + |
95 | + output = [] |
96 | + for entry in src: |
97 | + if entry.dist in suites_to_disable and not entry.disabled: |
98 | + # handle commenting ourselves - it handles lines with |
99 | + # options better |
100 | + entry = SourceEntry('# ' + str(entry)) |
101 | + output.append(entry) |
102 | + return output |
103 | |
104 | - newsrc = "" |
105 | - for line in retsrc.splitlines(True): |
106 | - if line.startswith("#"): |
107 | - newsrc += line |
108 | - continue |
109 | |
110 | - # sources.list allow options in cols[1] which can have spaces |
111 | - # so the actual suite can be [2] or later. example: |
112 | - # deb [ arch=amd64,armel k=v ] http://example.com/debian |
113 | - cols = line.split() |
114 | - if len(cols) > 1: |
115 | - pcol = 2 |
116 | - if cols[1].startswith("["): |
117 | - for col in cols[1:]: |
118 | - pcol += 1 |
119 | - if col.endswith("]"): |
120 | - break |
121 | +def update_dist(entries, release): |
122 | + for entry in entries: |
123 | + entry.dist = util.render_string(entry.dist, {'RELEASE': release}) |
124 | + return entries |
125 | |
126 | - if cols[pcol] == releasesuite: |
127 | - line = '# suite disabled by curtin: %s' % line |
128 | - newsrc += line |
129 | - retsrc = newsrc |
130 | |
131 | - return retsrc |
132 | +def entries_to_str(entries): |
133 | + return ''.join([str(entry) + '\n' for entry in entries]) |
134 | |
135 | |
136 | def generate_sources_list(cfg, release, mirrors, target=None): |
137 | @@ -285,34 +297,31 @@ def generate_sources_list(cfg, release, mirrors, target=None): |
138 | create a source.list file based on a custom or default template |
139 | by replacing mirrors and release in the template |
140 | """ |
141 | - default_mirrors = get_default_mirrors(distro.get_architecture(target)) |
142 | aptsrc = "/etc/apt/sources.list" |
143 | - params = {'RELEASE': release} |
144 | - for k in mirrors: |
145 | - params[k] = mirrors[k] |
146 | |
147 | tmpl = cfg.get('sources_list', None) |
148 | + from_file = False |
149 | if tmpl is None: |
150 | LOG.info("No custom template provided, fall back to modify" |
151 | "mirrors in %s on the target system", aptsrc) |
152 | tmpl = util.load_file(paths.target_path(target, aptsrc)) |
153 | - # Strategy if no custom template was provided: |
154 | - # - Only replacing mirrors |
155 | - # - no reason to replace "release" as it is from target anyway |
156 | - # - The less we depend upon, the more stable this is against changes |
157 | - # - warn if expected original content wasn't found |
158 | - tmpl = mirror_to_placeholder(tmpl, default_mirrors['PRIMARY'], |
159 | - "$MIRROR") |
160 | - tmpl = mirror_to_placeholder(tmpl, default_mirrors['SECURITY'], |
161 | - "$SECURITY") |
162 | + from_file = True |
163 | + |
164 | + entries = [SourceEntry(line) for line in tmpl.splitlines(True)] |
165 | + if from_file: |
166 | + # when loading from an existing file, we also replace default |
167 | + # URIs with configured mirrors |
168 | + entries = update_default_mirrors(entries, mirrors, target) |
169 | + |
170 | + entries = update_mirrors(entries, mirrors) |
171 | + entries = update_dist(entries, release) |
172 | + entries = disable_suites(cfg.get('disable_suites'), entries, release) |
173 | + output = entries_to_str(entries) |
174 | |
175 | orig = paths.target_path(target, aptsrc) |
176 | if os.path.exists(orig): |
177 | os.rename(orig, orig + ".curtin.old") |
178 | - |
179 | - rendered = util.render_string(tmpl, params) |
180 | - disabled = disable_suites(cfg.get('disable_suites'), rendered, release) |
181 | - util.write_file(paths.target_path(target, aptsrc), disabled, mode=0o644) |
182 | + util.write_file(paths.target_path(target, aptsrc), output, mode=0o644) |
183 | |
184 | |
185 | def apply_preserve_sources_list(target): |
186 | diff --git a/tests/unittests/test_apt_source.py b/tests/unittests/test_apt_source.py |
187 | index 6556399..01e70ad 100644 |
188 | --- a/tests/unittests/test_apt_source.py |
189 | +++ b/tests/unittests/test_apt_source.py |
190 | @@ -12,6 +12,8 @@ import socket |
191 | import mock |
192 | from mock import call |
193 | |
194 | +from aptsources.sourceslist import SourceEntry |
195 | + |
196 | from curtin import distro |
197 | from curtin import gpg |
198 | from curtin import util |
199 | @@ -63,6 +65,18 @@ class PseudoChrootableTarget(util.ChrootableTarget): |
200 | ChrootableTargetStr = "curtin.commands.apt_config.util.ChrootableTarget" |
201 | |
202 | |
203 | +def entryify(data): |
204 | + return [SourceEntry(line) for line in data.splitlines()] |
205 | + |
206 | + |
207 | +def lineify(entries): |
208 | + out = apt_config.entries_to_str(entries) |
209 | + # the tests are written without the trailing newline, |
210 | + # but we don't want to remove multiple of them |
211 | + out = out[:-1] if len(out) > 0 and out[-1] == '\n' else out |
212 | + return out |
213 | + |
214 | + |
215 | class TestAptSourceConfig(CiTestCase): |
216 | """ TestAptSourceConfig |
217 | Main Class to test apt configs |
218 | @@ -77,6 +91,7 @@ class TestAptSourceConfig(CiTestCase): |
219 | self.matcher = re.compile(ADD_APT_REPO_MATCH).search |
220 | self.add_patch('curtin.util.subp', 'm_subp') |
221 | self.m_subp.return_value = ('s390x', '') |
222 | + self.target = self.tmp_dir() |
223 | |
224 | @staticmethod |
225 | def _add_apt_sources(*args, **kwargs): |
226 | @@ -758,6 +773,7 @@ class TestAptSourceConfig(CiTestCase): |
227 | def test_disable_suites(self): |
228 | """test_disable_suites - disable_suites with many configurations""" |
229 | release = "xenial" |
230 | + |
231 | orig = """deb http://ubuntu.com//ubuntu xenial main |
232 | deb http://ubuntu.com//ubuntu xenial-updates main |
233 | deb http://ubuntu.com//ubuntu xenial-security main |
234 | @@ -771,39 +787,38 @@ deb http://ubuntu.com//ubuntu xenial-updates main |
235 | deb http://ubuntu.com//ubuntu xenial-security main |
236 | deb-src http://ubuntu.com//ubuntu universe multiverse |
237 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
238 | - result = apt_config.disable_suites(disabled, orig, release) |
239 | - self.assertEqual(expect, result) |
240 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
241 | + self.assertEqual(expect, lineify(result)) |
242 | |
243 | # single disable release suite |
244 | disabled = ["$RELEASE"] |
245 | - expect = """\ |
246 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial main |
247 | + expect = """# deb http://ubuntu.com//ubuntu xenial main |
248 | deb http://ubuntu.com//ubuntu xenial-updates main |
249 | deb http://ubuntu.com//ubuntu xenial-security main |
250 | deb-src http://ubuntu.com//ubuntu universe multiverse |
251 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
252 | - result = apt_config.disable_suites(disabled, orig, release) |
253 | - self.assertEqual(expect, result) |
254 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
255 | + self.assertEqual(expect, lineify(result)) |
256 | |
257 | # single disable other suite |
258 | disabled = ["$RELEASE-updates"] |
259 | expect = """deb http://ubuntu.com//ubuntu xenial main |
260 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main |
261 | +# deb http://ubuntu.com//ubuntu xenial-updates main |
262 | deb http://ubuntu.com//ubuntu xenial-security main |
263 | deb-src http://ubuntu.com//ubuntu universe multiverse |
264 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
265 | - result = apt_config.disable_suites(disabled, orig, release) |
266 | - self.assertEqual(expect, result) |
267 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
268 | + self.assertEqual(expect, lineify(result)) |
269 | |
270 | # multi disable |
271 | disabled = ["$RELEASE-updates", "$RELEASE-security"] |
272 | expect = """deb http://ubuntu.com//ubuntu xenial main |
273 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main |
274 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main |
275 | +# deb http://ubuntu.com//ubuntu xenial-updates main |
276 | +# deb http://ubuntu.com//ubuntu xenial-security main |
277 | deb-src http://ubuntu.com//ubuntu universe multiverse |
278 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
279 | - result = apt_config.disable_suites(disabled, orig, release) |
280 | - self.assertEqual(expect, result) |
281 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
282 | + self.assertEqual(expect, lineify(result)) |
283 | |
284 | # multi line disable (same suite multiple times in input) |
285 | disabled = ["$RELEASE-updates", "$RELEASE-security"] |
286 | @@ -815,14 +830,14 @@ deb http://UBUNTU.com//ubuntu xenial-updates main |
287 | deb http://UBUNTU.COM//ubuntu xenial-updates main |
288 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
289 | expect = """deb http://ubuntu.com//ubuntu xenial main |
290 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main |
291 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main |
292 | +# deb http://ubuntu.com//ubuntu xenial-updates main |
293 | +# deb http://ubuntu.com//ubuntu xenial-security main |
294 | deb-src http://ubuntu.com//ubuntu universe multiverse |
295 | -# suite disabled by curtin: deb http://UBUNTU.com//ubuntu xenial-updates main |
296 | -# suite disabled by curtin: deb http://UBUNTU.COM//ubuntu xenial-updates main |
297 | +# deb http://UBUNTU.com//ubuntu xenial-updates main |
298 | +# deb http://UBUNTU.COM//ubuntu xenial-updates main |
299 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
300 | - result = apt_config.disable_suites(disabled, orig, release) |
301 | - self.assertEqual(expect, result) |
302 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
303 | + self.assertEqual(expect, lineify(result)) |
304 | |
305 | # comment in input |
306 | disabled = ["$RELEASE-updates", "$RELEASE-security"] |
307 | @@ -835,15 +850,15 @@ deb-src http://ubuntu.com//ubuntu universe multiverse |
308 | deb http://UBUNTU.COM//ubuntu xenial-updates main |
309 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
310 | expect = """deb http://ubuntu.com//ubuntu xenial main |
311 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main |
312 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main |
313 | +# deb http://ubuntu.com//ubuntu xenial-updates main |
314 | +# deb http://ubuntu.com//ubuntu xenial-security main |
315 | deb-src http://ubuntu.com//ubuntu universe multiverse |
316 | #foo |
317 | -#deb http://UBUNTU.com//ubuntu xenial-updates main |
318 | -# suite disabled by curtin: deb http://UBUNTU.COM//ubuntu xenial-updates main |
319 | +# deb http://UBUNTU.com//ubuntu xenial-updates main |
320 | +# deb http://UBUNTU.COM//ubuntu xenial-updates main |
321 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
322 | - result = apt_config.disable_suites(disabled, orig, release) |
323 | - self.assertEqual(expect, result) |
324 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
325 | + self.assertEqual(expect, lineify(result)) |
326 | |
327 | # single disable custom suite |
328 | disabled = ["foobar"] |
329 | @@ -854,9 +869,9 @@ deb http://ubuntu.com/ubuntu/ foobar main""" |
330 | expect = """deb http://ubuntu.com//ubuntu xenial main |
331 | deb http://ubuntu.com//ubuntu xenial-updates main |
332 | deb http://ubuntu.com//ubuntu xenial-security main |
333 | -# suite disabled by curtin: deb http://ubuntu.com/ubuntu/ foobar main""" |
334 | - result = apt_config.disable_suites(disabled, orig, release) |
335 | - self.assertEqual(expect, result) |
336 | +# deb http://ubuntu.com/ubuntu/ foobar main""" |
337 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
338 | + self.assertEqual(expect, lineify(result)) |
339 | |
340 | # single disable non existing suite |
341 | disabled = ["foobar"] |
342 | @@ -868,8 +883,8 @@ deb http://ubuntu.com/ubuntu/ notfoobar main""" |
343 | deb http://ubuntu.com//ubuntu xenial-updates main |
344 | deb http://ubuntu.com//ubuntu xenial-security main |
345 | deb http://ubuntu.com/ubuntu/ notfoobar main""" |
346 | - result = apt_config.disable_suites(disabled, orig, release) |
347 | - self.assertEqual(expect, result) |
348 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
349 | + self.assertEqual(expect, lineify(result)) |
350 | |
351 | # single disable suite with option |
352 | disabled = ["$RELEASE-updates"] |
353 | @@ -879,12 +894,12 @@ deb http://ubuntu.com//ubuntu xenial-security main |
354 | deb-src http://ubuntu.com//ubuntu universe multiverse |
355 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
356 | expect = """deb http://ubuntu.com//ubuntu xenial main |
357 | -# suite disabled by curtin: deb [a=b] http://ubu.com//ubu xenial-updates main |
358 | +# deb [a=b] http://ubu.com//ubu xenial-updates main |
359 | deb http://ubuntu.com//ubuntu xenial-security main |
360 | deb-src http://ubuntu.com//ubuntu universe multiverse |
361 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
362 | - result = apt_config.disable_suites(disabled, orig, release) |
363 | - self.assertEqual(expect, result) |
364 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
365 | + self.assertEqual(expect, lineify(result)) |
366 | |
367 | # single disable suite with more options and auto $RELEASE expansion |
368 | disabled = ["updates"] |
369 | @@ -894,13 +909,12 @@ deb http://ubuntu.com//ubuntu xenial-security main |
370 | deb-src http://ubuntu.com//ubuntu universe multiverse |
371 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
372 | expect = """deb http://ubuntu.com//ubuntu xenial main |
373 | -# suite disabled by curtin: deb [a=b c=d] \ |
374 | -http://ubu.com//ubu xenial-updates main |
375 | +# deb [a=b c=d] http://ubu.com//ubu xenial-updates main |
376 | deb http://ubuntu.com//ubuntu xenial-security main |
377 | deb-src http://ubuntu.com//ubuntu universe multiverse |
378 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
379 | - result = apt_config.disable_suites(disabled, orig, release) |
380 | - self.assertEqual(expect, result) |
381 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
382 | + self.assertEqual(expect, lineify(result)) |
383 | |
384 | # single disable suite while options at others |
385 | disabled = ["$RELEASE-security"] |
386 | @@ -911,25 +925,74 @@ deb-src http://ubuntu.com//ubuntu universe multiverse |
387 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
388 | expect = """deb http://ubuntu.com//ubuntu xenial main |
389 | deb [arch=foo] http://ubuntu.com//ubuntu xenial-updates main |
390 | -# suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main |
391 | +# deb http://ubuntu.com//ubuntu xenial-security main |
392 | deb-src http://ubuntu.com//ubuntu universe multiverse |
393 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" |
394 | - result = apt_config.disable_suites(disabled, orig, release) |
395 | - self.assertEqual(expect, result) |
396 | + result = apt_config.disable_suites(disabled, entryify(orig), release) |
397 | + self.assertEqual(expect, lineify(result)) |
398 | |
399 | def test_disable_suites_blank_lines(self): |
400 | """test_disable_suites_blank_lines - ensure blank lines allowed""" |
401 | - lines = ["deb %(repo)s %(rel)s main universe", |
402 | - "", |
403 | - "deb %(repo)s %(rel)s-updates main universe", |
404 | - " # random comment", |
405 | - "#comment here", |
406 | - ""] |
407 | rel = "trusty" |
408 | - repo = 'http://example.com/mirrors/ubuntu' |
409 | - orig = "\n".join(lines) % {'repo': repo, 'rel': rel} |
410 | - self.assertEqual( |
411 | - orig, apt_config.disable_suites(["proposed"], orig, rel)) |
412 | + |
413 | + orig = """ |
414 | +deb http://example.com/mirrors/ubuntu trusty main universe |
415 | + |
416 | +deb http://example.com/mirrors/ubuntu trusty-updates main universe |
417 | + |
418 | +deb http://example.com/mirrors/ubuntu trusty-proposed main universe |
419 | + |
420 | +#comment here""" |
421 | + expect = """ |
422 | +deb http://example.com/mirrors/ubuntu trusty main universe |
423 | + |
424 | +deb http://example.com/mirrors/ubuntu trusty-updates main universe |
425 | + |
426 | +# deb http://example.com/mirrors/ubuntu trusty-proposed main universe |
427 | + |
428 | +#comment here""" |
429 | + disabled = ["proposed"] |
430 | + result = apt_config.disable_suites(disabled, entryify(orig), rel) |
431 | + self.assertEqual(expect, lineify(result)) |
432 | + |
433 | + @mock.patch("curtin.util.write_file") |
434 | + @mock.patch("curtin.distro.get_architecture") |
435 | + def test_generate_with_options(self, get_arch, write_file): |
436 | + get_arch.return_value = "amd64" |
437 | + orig = """deb http://ubuntu.com//ubuntu $RELEASE main |
438 | +# stuff things |
439 | + |
440 | +deb http://ubuntu.com//ubuntu $RELEASE-updates main |
441 | +deb http://ubuntu.com//ubuntu $RELEASE-security main |
442 | +deb-src http://ubuntu.com//ubuntu $RELEASE universe multiverse |
443 | +# deb http://ubuntu.com/ubuntu/ $RELEASE-proposed main |
444 | +deb [a=b] http://ubuntu.com/ubuntu/ $RELEASE-backports main |
445 | +""" |
446 | + expect = """deb http://ubuntu.com//ubuntu xenial main |
447 | +# stuff things |
448 | + |
449 | +deb http://ubuntu.com//ubuntu xenial-updates main |
450 | +deb http://ubuntu.com//ubuntu xenial-security main |
451 | +deb-src http://ubuntu.com//ubuntu xenial universe multiverse |
452 | +# deb http://ubuntu.com/ubuntu/ xenial-proposed main |
453 | +# deb [a=b] http://ubuntu.com/ubuntu/ $RELEASE-backports main |
454 | +""" |
455 | + # $RELEASE in backports doesn't get expanded because the line is |
456 | + # considered invalid because of the options. So when the line |
457 | + # gets commented out, it comments out the original line, not |
458 | + # what we've modifed it to. |
459 | + rel = 'xenial' |
460 | + mirrors = {'PRIMARY': 'http://ubuntu.com/ubuntu/'} |
461 | + |
462 | + cfg = { |
463 | + 'preserve_sources_list': False, |
464 | + 'sources_list': orig, |
465 | + 'disable_suites': ['backports'], |
466 | + } |
467 | + |
468 | + apt_config.generate_sources_list(cfg, rel, mirrors, self.target) |
469 | + filepath = os.path.join(self.target, 'etc/apt/sources.list') |
470 | + write_file.assert_called_with(filepath, expect, mode=0o644) |
471 | |
472 | |
473 | class TestDebconfSelections(CiTestCase): |
474 | diff --git a/tests/vmtests/__init__.py b/tests/vmtests/__init__.py |
475 | index 0b19d8f..fd6c246 100644 |
476 | --- a/tests/vmtests/__init__.py |
477 | +++ b/tests/vmtests/__init__.py |
478 | @@ -1631,6 +1631,9 @@ class VMBaseClass(TestCase): |
479 | def check_file_regex(self, filename, regex): |
480 | self.assertRegex(self.load_collect_file(filename), regex) |
481 | |
482 | + def not_file_regex(self, filename, regex): |
483 | + self.assertNotRegex(self.load_collect_file(filename), regex) |
484 | + |
485 | # To get rid of deprecation warning in python 3. |
486 | def assertRegex(self, s, r): |
487 | try: |
488 | @@ -1640,6 +1643,14 @@ class VMBaseClass(TestCase): |
489 | # Python 2. |
490 | self.assertRegexpMatches(s, r) |
491 | |
492 | + def assertNotRegex(self, s, r): |
493 | + try: |
494 | + # Python 3. |
495 | + super(VMBaseClass, self).assertNotRegex(s, r) |
496 | + except AttributeError: |
497 | + # Python 2. |
498 | + self.assertNotRegexpMatches(s, r) |
499 | + |
500 | def get_blkid_data(self, blkid_file): |
501 | data = self.load_collect_file(blkid_file) |
502 | ret = {} |
503 | diff --git a/tests/vmtests/test_apt_source.py b/tests/vmtests/test_apt_source.py |
504 | index a090ffa..9d00dc8 100644 |
505 | --- a/tests/vmtests/test_apt_source.py |
506 | +++ b/tests/vmtests/test_apt_source.py |
507 | @@ -164,9 +164,8 @@ class TestAptSrcDisablePockets(TestAptSrcAbs): |
508 | r"deb.*us.archive.ubuntu.com") |
509 | self.check_file_regex("sources.list", |
510 | r"deb.*security.ubuntu.com") |
511 | - # updates disabled |
512 | - self.check_file_regex("sources.list", |
513 | - r"# suite disabled by curtin:.*-updates") |
514 | + # updates disabled and not present |
515 | + self.not_file_regex("sources.list", r"# .*-updates") |
516 | |
517 | |
518 | class TestAptSrcModifyArches(TestAptSrcModify): |
519 | diff --git a/tox.ini b/tox.ini |
520 | index f27dfbc..d9437c5 100644 |
521 | --- a/tox.ini |
522 | +++ b/tox.ini |
523 | @@ -71,6 +71,7 @@ commands = {envpython} -m pylint --errors-only {posargs:curtin tests/vmtests} |
524 | [testenv:py27-pylint] |
525 | # set basepython because tox 1.6 (trusty) does not support generated environments |
526 | basepython = python2.7 |
527 | +sitepackages = true |
528 | deps = {[testenv]deps} |
529 | {[testenv:py27]deps} |
530 | pylint==1.8.1 |
FAILED: Continuous integration, rev:3e77e3070d5 915f7a79b16518a ae9cf5fb2087fb /jenkins. ubuntu. com/server/ job/curtin- ci/175/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-amd64/ 175/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-arm64/ 175/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-ppc64el/ 175/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-s390x/ 175/
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/curtin- ci/175/ /rebuild
https:/