Merge lp:~cjwatson/launchpad-buildd/gather-results-via-backend into lp:launchpad-buildd
- gather-results-via-backend
- Merge into trunk
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 259 |
Proposed branch: | lp:~cjwatson/launchpad-buildd/gather-results-via-backend |
Merge into: | lp:launchpad-buildd |
Prerequisite: | lp:~cjwatson/launchpad-buildd/fake-backend |
Diff against target: |
737 lines (+287/-90) 13 files modified
lpbuildd/livefs.py (+5/-11) lpbuildd/slave.py (+11/-0) lpbuildd/snap.py (+5/-11) lpbuildd/target/apt.py (+2/-0) lpbuildd/target/backend.py (+54/-1) lpbuildd/target/chroot.py (+18/-5) lpbuildd/target/tests/test_apt.py (+5/-4) lpbuildd/target/tests/test_chroot.py (+91/-0) lpbuildd/tests/fakeslave.py (+50/-2) lpbuildd/tests/test_livefs.py (+15/-18) lpbuildd/tests/test_snap.py (+15/-20) lpbuildd/tests/test_translationtemplatesbuildmanager.py (+13/-12) lpbuildd/translationtemplates.py (+3/-6) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad-buildd/gather-results-via-backend |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+328624@code.launchpad.net |
Commit message
Gather results via the backend abstraction rather than by direct filesystem access.
Description of the change
Current exceptions are binarypackage (because sbuild handles its own backend access) and sourcepackagerecipe (which needs some further refactoring first).
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
- 258. By Colin Watson
-
Merge trunk.
- 259. By Colin Watson
-
Preserve timestamps in Chroot.copy_out, but not ownership/
permissions.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lpbuildd/livefs.py' |
2 | --- lpbuildd/livefs.py 2017-07-28 13:57:47 +0000 |
3 | +++ lpbuildd/livefs.py 2017-08-22 16:03:15 +0000 |
4 | @@ -4,12 +4,10 @@ |
5 | __metaclass__ = type |
6 | |
7 | import os |
8 | -import shutil |
9 | |
10 | from lpbuildd.debian import ( |
11 | DebianBuildManager, |
12 | DebianBuildState, |
13 | - get_build_path, |
14 | ) |
15 | |
16 | |
17 | @@ -33,11 +31,6 @@ |
18 | |
19 | def initiate(self, files, chroot, extra_args): |
20 | """Initiate a build with a given set of files and chroot.""" |
21 | - self.build_path = get_build_path( |
22 | - self.home, self._buildid, "chroot-autobuild", "build") |
23 | - if os.path.isdir(self.build_path): |
24 | - shutil.rmtree(self.build_path) |
25 | - |
26 | self.subarch = extra_args.get("subarch") |
27 | self.project = extra_args["project"] |
28 | self.subproject = extra_args.get("subproject") |
29 | @@ -100,7 +93,8 @@ |
30 | |
31 | def gatherResults(self): |
32 | """Gather the results of the build and add them to the file cache.""" |
33 | - for entry in sorted(os.listdir(self.build_path)): |
34 | - path = os.path.join(self.build_path, entry) |
35 | - if entry.startswith("livecd.") and not os.path.islink(path): |
36 | - self._slave.addWaitingFile(path) |
37 | + for entry in sorted(self.backend.listdir("/build")): |
38 | + path = os.path.join("/build", entry) |
39 | + if (entry.startswith("livecd.") and |
40 | + not self.backend.islink(path)): |
41 | + self.addWaitingFileFromBackend(path) |
42 | |
43 | === modified file 'lpbuildd/slave.py' |
44 | --- lpbuildd/slave.py 2017-08-22 14:46:10 +0000 |
45 | +++ lpbuildd/slave.py 2017-08-22 16:03:15 +0000 |
46 | @@ -12,6 +12,8 @@ |
47 | import hashlib |
48 | import os |
49 | import re |
50 | +import shutil |
51 | +import tempfile |
52 | import urllib2 |
53 | import xmlrpclib |
54 | |
55 | @@ -307,6 +309,15 @@ |
56 | self._subprocess.ignore = True |
57 | self._subprocess.transport.loseConnection() |
58 | |
59 | + def addWaitingFileFromBackend(self, path): |
60 | + fetched_dir = tempfile.mkdtemp() |
61 | + try: |
62 | + fetched_path = os.path.join(fetched_dir, os.path.basename(path)) |
63 | + self.backend.copy_out(path, fetched_path) |
64 | + self._slave.addWaitingFile(fetched_path) |
65 | + finally: |
66 | + shutil.rmtree(fetched_dir) |
67 | + |
68 | |
69 | class BuilderStatus: |
70 | """Status values for the builder.""" |
71 | |
72 | === modified file 'lpbuildd/snap.py' |
73 | --- lpbuildd/snap.py 2017-04-03 12:30:15 +0000 |
74 | +++ lpbuildd/snap.py 2017-08-22 16:03:15 +0000 |
75 | @@ -7,7 +7,6 @@ |
76 | |
77 | import json |
78 | import os |
79 | -import shutil |
80 | import sys |
81 | |
82 | from lpbuildd.debian import ( |
83 | @@ -41,11 +40,6 @@ |
84 | |
85 | def initiate(self, files, chroot, extra_args): |
86 | """Initiate a build with a given set of files and chroot.""" |
87 | - self.build_path = get_build_path( |
88 | - self.home, self._buildid, "chroot-autobuild", "build") |
89 | - if os.path.isdir(self.build_path): |
90 | - shutil.rmtree(self.build_path) |
91 | - |
92 | self.name = extra_args["name"] |
93 | self.branch = extra_args.get("branch") |
94 | self.git_repository = extra_args.get("git_repository") |
95 | @@ -113,12 +107,12 @@ |
96 | |
97 | def gatherResults(self): |
98 | """Gather the results of the build and add them to the file cache.""" |
99 | - output_path = os.path.join(self.build_path, self.name) |
100 | - if not os.path.exists(output_path): |
101 | + output_path = os.path.join("/build", self.name) |
102 | + if not self.backend.path_exists(output_path): |
103 | return |
104 | - for entry in sorted(os.listdir(output_path)): |
105 | + for entry in sorted(self.backend.listdir(output_path)): |
106 | path = os.path.join(output_path, entry) |
107 | - if os.path.islink(path): |
108 | + if self.backend.islink(path): |
109 | continue |
110 | if entry.endswith(".snap") or entry.endswith(".manifest"): |
111 | - self._slave.addWaitingFile(path) |
112 | + self.addWaitingFileFromBackend(path) |
113 | |
114 | === modified file 'lpbuildd/target/apt.py' |
115 | --- lpbuildd/target/apt.py 2017-08-22 13:48:08 +0000 |
116 | +++ lpbuildd/target/apt.py 2017-08-22 16:03:15 +0000 |
117 | @@ -6,6 +6,7 @@ |
118 | __metaclass__ = type |
119 | |
120 | import logging |
121 | +import os |
122 | import subprocess |
123 | import sys |
124 | import tempfile |
125 | @@ -34,6 +35,7 @@ |
126 | for archive in self.args.archives: |
127 | print(archive, file=sources_list) |
128 | sources_list.flush() |
129 | + os.fchmod(sources_list.fileno(), 0o644) |
130 | self.backend.copy_in(sources_list.name, "/etc/apt/sources.list") |
131 | return 0 |
132 | |
133 | |
134 | === modified file 'lpbuildd/target/backend.py' |
135 | --- lpbuildd/target/backend.py 2017-08-22 15:09:09 +0000 |
136 | +++ lpbuildd/target/backend.py 2017-08-22 16:03:15 +0000 |
137 | @@ -36,12 +36,14 @@ |
138 | """ |
139 | raise NotImplementedError |
140 | |
141 | - def run(self, args, env=None, input_text=None, **kwargs): |
142 | + def run(self, args, env=None, input_text=None, get_output=False, |
143 | + **kwargs): |
144 | """Run a command in the target environment. |
145 | |
146 | :param args: the command and arguments to run. |
147 | :param env: additional environment variables to set. |
148 | :param input_text: input text to pass on the command's stdin. |
149 | + :param get_output: if True, return the output from the command. |
150 | :param kwargs: additional keyword arguments for `subprocess.Popen`. |
151 | """ |
152 | raise NotImplementedError |
153 | @@ -60,6 +62,57 @@ |
154 | """ |
155 | raise NotImplementedError |
156 | |
157 | + def copy_out(self, source_path, target_path): |
158 | + """Copy a file out of the target environment. |
159 | + |
160 | + The target file will have the same permission mode as the source |
161 | + file. |
162 | + |
163 | + :param source_path: the path to the file that should be copied, |
164 | + relative to the target environment's root. |
165 | + :param target_path: the path where the file should be installed in |
166 | + the host system. |
167 | + """ |
168 | + raise NotImplementedError |
169 | + |
170 | + def path_exists(self, path): |
171 | + """Test whether a path exists in the target environment. |
172 | + |
173 | + :param path: the path to the file to test, relative to the target |
174 | + environment's root. |
175 | + """ |
176 | + try: |
177 | + self.run(["test", "-e", path]) |
178 | + return True |
179 | + except subprocess.CalledProcessError: |
180 | + return False |
181 | + |
182 | + def islink(self, path): |
183 | + """Test whether a file is a symbolic link in the target environment. |
184 | + |
185 | + :param path: the path to the file to test, relative to the target |
186 | + environment's root. |
187 | + """ |
188 | + try: |
189 | + self.run(["test", "-h", path]) |
190 | + return True |
191 | + except subprocess.CalledProcessError: |
192 | + return False |
193 | + |
194 | + def listdir(self, path): |
195 | + """List a directory in the target environment. |
196 | + |
197 | + :param path: the path to the directory to list, relative to the |
198 | + target environment's root. |
199 | + """ |
200 | + paths = self.run( |
201 | + ["find", path, "-mindepth", "1", "-maxdepth", "1", |
202 | + "-printf", "%P\\0"], |
203 | + get_output=True).rstrip(b"\0").split(b"\0") |
204 | + # XXX cjwatson 2017-08-04: Use `os.fsdecode` instead once we're on |
205 | + # Python 3. |
206 | + return [path.decode("UTF-8") for path in paths] |
207 | + |
208 | def kill_processes(self): |
209 | """Kill any processes left running in the target. |
210 | |
211 | |
212 | === modified file 'lpbuildd/target/chroot.py' |
213 | --- lpbuildd/target/chroot.py 2017-08-04 13:08:31 +0000 |
214 | +++ lpbuildd/target/chroot.py 2017-08-22 16:03:15 +0000 |
215 | @@ -52,7 +52,8 @@ |
216 | for path in ("/etc/hosts", "/etc/hostname", "/etc/resolv.conf"): |
217 | self.copy_in(path, path) |
218 | |
219 | - def run(self, args, env=None, input_text=None, **kwargs): |
220 | + def run(self, args, env=None, input_text=None, get_output=False, |
221 | + **kwargs): |
222 | """See `Backend`.""" |
223 | if env: |
224 | args = ["env"] + [ |
225 | @@ -61,14 +62,17 @@ |
226 | if self.arch is not None: |
227 | args = set_personality(args, self.arch, series=self.series) |
228 | cmd = ["sudo", "/usr/sbin/chroot", self.chroot_path] + args |
229 | - if input_text is None: |
230 | + if input_text is None and not get_output: |
231 | subprocess.check_call(cmd, cwd=self.chroot_path, **kwargs) |
232 | else: |
233 | - proc = subprocess.Popen( |
234 | - cmd, stdin=subprocess.PIPE, universal_newlines=True, **kwargs) |
235 | - proc.communicate(input_text) |
236 | + if get_output: |
237 | + kwargs["stdout"] = subprocess.PIPE |
238 | + proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, **kwargs) |
239 | + output, _ = proc.communicate(input_text) |
240 | if proc.returncode: |
241 | raise subprocess.CalledProcessError(proc.returncode, cmd) |
242 | + if get_output: |
243 | + return output |
244 | |
245 | def copy_in(self, source_path, target_path): |
246 | """See `Backend`.""" |
247 | @@ -82,6 +86,15 @@ |
248 | ["sudo", "install", "-o", "root", "-g", "root", "-m", "%o" % mode, |
249 | source_path, full_target_path]) |
250 | |
251 | + def copy_out(self, source_path, target_path): |
252 | + # We can just use a plain copy here, since the file ownership in the |
253 | + # host system isn't important. |
254 | + full_source_path = os.path.join( |
255 | + self.chroot_path, source_path.lstrip("/")) |
256 | + subprocess.check_call( |
257 | + ["sudo", "cp", "--preserve=timestamps", |
258 | + full_source_path, target_path]) |
259 | + |
260 | def kill_processes(self): |
261 | """See `Backend`.""" |
262 | prefix = os.path.realpath(self.chroot_path) |
263 | |
264 | === modified file 'lpbuildd/target/tests/test_apt.py' |
265 | --- lpbuildd/target/tests/test_apt.py 2017-08-22 15:09:09 +0000 |
266 | +++ lpbuildd/target/tests/test_apt.py 2017-08-22 16:03:15 +0000 |
267 | @@ -4,6 +4,7 @@ |
268 | __metaclass__ = type |
269 | |
270 | import io |
271 | +import stat |
272 | import subprocess |
273 | from textwrap import dedent |
274 | import time |
275 | @@ -45,12 +46,12 @@ |
276 | ] |
277 | override_sources_list = parse_args(args=args).operation |
278 | self.assertEqual(0, override_sources_list.run()) |
279 | - self.assertEqual({ |
280 | - "/etc/apt/sources.list": dedent("""\ |
281 | + self.assertEqual( |
282 | + (dedent("""\ |
283 | deb http://archive.ubuntu.com/ubuntu xenial main |
284 | deb http://ppa.launchpad.net/launchpad/ppa/ubuntu xenial main |
285 | - """).encode("UTF-8"), |
286 | - }, override_sources_list.backend.copied_in) |
287 | + """).encode("UTF-8"), stat.S_IFREG | 0o644), |
288 | + override_sources_list.backend.backend_fs["/etc/apt/sources.list"]) |
289 | |
290 | |
291 | class TestAddTrustedKeys(TestCase): |
292 | |
293 | === modified file 'lpbuildd/target/tests/test_chroot.py' |
294 | --- lpbuildd/target/tests/test_chroot.py 2017-08-04 13:08:31 +0000 |
295 | +++ lpbuildd/target/tests/test_chroot.py 2017-08-22 16:03:15 +0000 |
296 | @@ -3,6 +3,7 @@ |
297 | |
298 | __metaclass__ = type |
299 | |
300 | +import io |
301 | import os.path |
302 | import signal |
303 | from textwrap import dedent |
304 | @@ -97,6 +98,25 @@ |
305 | expected_args, |
306 | [proc._args["args"] for proc in processes_fixture.procs]) |
307 | |
308 | + def test_run_get_output(self): |
309 | + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) |
310 | + processes_fixture = self.useFixture(FakeProcesses()) |
311 | + processes_fixture.add( |
312 | + lambda _: {"stdout": io.BytesIO(b"hello\n")}, name="sudo") |
313 | + self.assertEqual( |
314 | + "hello\n", |
315 | + Chroot("1", "xenial", "amd64").run( |
316 | + ["echo", "hello"], get_output=True)) |
317 | + |
318 | + expected_args = [ |
319 | + ["sudo", "/usr/sbin/chroot", |
320 | + "/expected/home/build-1/chroot-autobuild", |
321 | + "linux64", "echo", "hello"], |
322 | + ] |
323 | + self.assertEqual( |
324 | + expected_args, |
325 | + [proc._args["args"] for proc in processes_fixture.procs]) |
326 | + |
327 | def test_copy_in(self): |
328 | self.useFixture(EnvironmentVariable("HOME", "/expected/home")) |
329 | source_dir = self.useFixture(TempDir()).path |
330 | @@ -119,6 +139,77 @@ |
331 | expected_args, |
332 | [proc._args["args"] for proc in processes_fixture.procs]) |
333 | |
334 | + def test_copy_out(self): |
335 | + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) |
336 | + processes_fixture = self.useFixture(FakeProcesses()) |
337 | + processes_fixture.add(lambda _: {}, name="sudo") |
338 | + Chroot("1", "xenial", "amd64").copy_out( |
339 | + "/path/to/source", "/path/to/target") |
340 | + |
341 | + expected_args = [ |
342 | + ["sudo", "cp", "--preserve=timestamps", |
343 | + "/expected/home/build-1/chroot-autobuild/path/to/source", |
344 | + "/path/to/target"], |
345 | + ] |
346 | + self.assertEqual( |
347 | + expected_args, |
348 | + [proc._args["args"] for proc in processes_fixture.procs]) |
349 | + |
350 | + def test_path_exists(self): |
351 | + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) |
352 | + processes_fixture = self.useFixture(FakeProcesses()) |
353 | + test_proc_infos = iter([{}, {"returncode": 1}]) |
354 | + processes_fixture.add(lambda _: next(test_proc_infos), name="sudo") |
355 | + self.assertTrue(Chroot("1", "xenial", "amd64").path_exists("/present")) |
356 | + self.assertFalse(Chroot("1", "xenial", "amd64").path_exists("/absent")) |
357 | + |
358 | + expected_args = [ |
359 | + ["sudo", "/usr/sbin/chroot", |
360 | + "/expected/home/build-1/chroot-autobuild", |
361 | + "linux64", "test", "-e", path] |
362 | + for path in ("/present", "/absent") |
363 | + ] |
364 | + self.assertEqual( |
365 | + expected_args, |
366 | + [proc._args["args"] for proc in processes_fixture.procs]) |
367 | + |
368 | + def test_islink(self): |
369 | + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) |
370 | + processes_fixture = self.useFixture(FakeProcesses()) |
371 | + test_proc_infos = iter([{}, {"returncode": 1}]) |
372 | + processes_fixture.add(lambda _: next(test_proc_infos), name="sudo") |
373 | + self.assertTrue(Chroot("1", "xenial", "amd64").islink("/link")) |
374 | + self.assertFalse(Chroot("1", "xenial", "amd64").islink("/file")) |
375 | + |
376 | + expected_args = [ |
377 | + ["sudo", "/usr/sbin/chroot", |
378 | + "/expected/home/build-1/chroot-autobuild", |
379 | + "linux64", "test", "-h", path] |
380 | + for path in ("/link", "/file") |
381 | + ] |
382 | + self.assertEqual( |
383 | + expected_args, |
384 | + [proc._args["args"] for proc in processes_fixture.procs]) |
385 | + |
386 | + def test_listdir(self): |
387 | + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) |
388 | + processes_fixture = self.useFixture(FakeProcesses()) |
389 | + processes_fixture.add( |
390 | + lambda _: {"stdout": io.BytesIO(b"foo\0bar\0baz\0")}, name="sudo") |
391 | + self.assertEqual( |
392 | + ["foo", "bar", "baz"], |
393 | + Chroot("1", "xenial", "amd64").listdir("/path")) |
394 | + |
395 | + expected_args = [ |
396 | + ["sudo", "/usr/sbin/chroot", |
397 | + "/expected/home/build-1/chroot-autobuild", |
398 | + "linux64", "find", "/path", "-mindepth", "1", "-maxdepth", "1", |
399 | + "-printf", "%P\\0"], |
400 | + ] |
401 | + self.assertEqual( |
402 | + expected_args, |
403 | + [proc._args["args"] for proc in processes_fixture.procs]) |
404 | + |
405 | def test_kill_processes(self): |
406 | self.useFixture(EnvironmentVariable("HOME", "/expected/home")) |
407 | fs_fixture = self.useFixture(FakeFilesystem()) |
408 | |
409 | === modified file 'lpbuildd/tests/fakeslave.py' |
410 | --- lpbuildd/tests/fakeslave.py 2017-08-05 00:09:13 +0000 |
411 | +++ lpbuildd/tests/fakeslave.py 2017-08-22 16:03:15 +0000 |
412 | @@ -10,6 +10,7 @@ |
413 | import hashlib |
414 | import os |
415 | import shutil |
416 | +import stat |
417 | |
418 | from lpbuildd.target.backend import Backend |
419 | |
420 | @@ -117,8 +118,55 @@ |
421 | ) |
422 | for fake_method in fake_methods: |
423 | setattr(self, fake_method, FakeMethod()) |
424 | - self.copied_in = {} |
425 | + self.backend_fs = {} |
426 | + |
427 | + def _add_inode(self, path, contents, full_mode): |
428 | + path = os.path.normpath(path) |
429 | + parent = os.path.dirname(path) |
430 | + if parent != path and parent not in self.backend_fs: |
431 | + self.add_dir(parent) |
432 | + self.backend_fs[path] = (contents, full_mode) |
433 | + |
434 | + def add_dir(self, path, mode=0o755): |
435 | + self._add_inode(path, None, stat.S_IFDIR | mode) |
436 | + |
437 | + def add_file(self, path, contents, mode=0o644): |
438 | + self._add_inode(path, contents, stat.S_IFREG | mode) |
439 | + |
440 | + def add_link(self, path, target): |
441 | + self._add_inode(path, target, stat.S_IFLNK | 0o777) |
442 | |
443 | def copy_in(self, source_path, target_path): |
444 | with open(source_path, "rb") as source: |
445 | - self.copied_in[target_path] = source.read() |
446 | + self.add_file( |
447 | + target_path, source.read(), os.fstat(source.fileno()).st_mode) |
448 | + |
449 | + def _get_inode(self, path): |
450 | + while True: |
451 | + contents, mode = self.backend_fs[path] |
452 | + if not stat.S_ISLNK(mode): |
453 | + return contents, mode |
454 | + path = os.path.normpath( |
455 | + os.path.join(os.path.dirname(path), contents)) |
456 | + |
457 | + def copy_out(self, source_path, target_path): |
458 | + contents, mode = self._get_inode(source_path) |
459 | + with open(target_path, "wb") as target: |
460 | + target.write(contents) |
461 | + os.fchmod(target.fileno(), stat.S_IMODE(mode)) |
462 | + |
463 | + def path_exists(self, path): |
464 | + try: |
465 | + self._get_inode(path) |
466 | + return True |
467 | + except KeyError: |
468 | + return False |
469 | + |
470 | + def islink(self, path): |
471 | + _, mode = self.backend_fs.get(path, (b"", 0)) |
472 | + return stat.S_ISLNK(mode) |
473 | + |
474 | + def listdir(self, path): |
475 | + return [ |
476 | + os.path.basename(p) for p in self.backend_fs |
477 | + if os.path.dirname(p) == path] |
478 | |
479 | === modified file 'lpbuildd/tests/test_livefs.py' |
480 | --- lpbuildd/tests/test_livefs.py 2017-08-22 14:53:29 +0000 |
481 | +++ lpbuildd/tests/test_livefs.py 2017-08-22 16:03:15 +0000 |
482 | @@ -4,9 +4,11 @@ |
483 | __metaclass__ = type |
484 | |
485 | import os |
486 | -import shutil |
487 | -import tempfile |
488 | |
489 | +from fixtures import ( |
490 | + EnvironmentVariable, |
491 | + TempDir, |
492 | + ) |
493 | from testtools import TestCase |
494 | |
495 | from lpbuildd.livefs import ( |
496 | @@ -35,19 +37,16 @@ |
497 | """Run LiveFilesystemBuildManager through its iteration steps.""" |
498 | def setUp(self): |
499 | super(TestLiveFilesystemBuildManagerIteration, self).setUp() |
500 | - self.working_dir = tempfile.mkdtemp() |
501 | - self.addCleanup(lambda: shutil.rmtree(self.working_dir)) |
502 | + self.working_dir = self.useFixture(TempDir()).path |
503 | slave_dir = os.path.join(self.working_dir, "slave") |
504 | home_dir = os.path.join(self.working_dir, "home") |
505 | for dir in (slave_dir, home_dir): |
506 | os.mkdir(dir) |
507 | + self.useFixture(EnvironmentVariable("HOME", home_dir)) |
508 | self.slave = FakeSlave(slave_dir) |
509 | self.buildid = "123" |
510 | self.buildmanager = MockBuildManager(self.slave, self.buildid) |
511 | - self.buildmanager.home = home_dir |
512 | self.buildmanager._cachepath = self.slave._cachepath |
513 | - self.build_dir = os.path.join( |
514 | - home_dir, "build-%s" % self.buildid, "chroot-autobuild", "build") |
515 | |
516 | def getState(self): |
517 | """Retrieve build manager's state.""" |
518 | @@ -62,7 +61,10 @@ |
519 | "pocket": "release", |
520 | "arch_tag": "i386", |
521 | } |
522 | + original_backend_name = self.buildmanager.backend_name |
523 | + self.buildmanager.backend_name = "fake" |
524 | self.buildmanager.initiate({}, "chroot.tar.gz", extra_args) |
525 | + self.buildmanager.backend_name = original_backend_name |
526 | |
527 | # Skip states that are done in DebianBuildManager to the state |
528 | # directly before BUILD_LIVEFS. |
529 | @@ -90,10 +92,8 @@ |
530 | with open(log_path, "w") as log: |
531 | log.write("I am a build log.") |
532 | |
533 | - os.makedirs(self.build_dir) |
534 | - manifest_path = os.path.join(self.build_dir, "livecd.ubuntu.manifest") |
535 | - with open(manifest_path, "w") as manifest: |
536 | - manifest.write("I am a manifest file.") |
537 | + self.buildmanager.backend.add_file( |
538 | + "/build/livecd.ubuntu.manifest", b"I am a manifest file.") |
539 | |
540 | # After building the package, reap processes. |
541 | self.buildmanager.iterate(0) |
542 | @@ -135,13 +135,10 @@ |
543 | with open(log_path, "w") as log: |
544 | log.write("I am a build log.") |
545 | |
546 | - os.makedirs(self.build_dir) |
547 | - target_path = os.path.join( |
548 | - self.build_dir, "livecd.ubuntu.kernel-generic") |
549 | - with open(target_path, "w") as target: |
550 | - target.write("I am a kernel.") |
551 | - link_path = os.path.join(self.build_dir, "livecd.ubuntu.kernel") |
552 | - os.symlink("livecd.ubuntu.kernel-generic", link_path) |
553 | + self.buildmanager.backend.add_file( |
554 | + "/build/livecd.ubuntu.kernel-generic", b"I am a kernel.") |
555 | + self.buildmanager.backend.add_link( |
556 | + "/build/livecd.ubuntu.kernel", "livefs.ubuntu.kernel-generic") |
557 | |
558 | self.buildmanager.iterate(0) |
559 | self.assertThat(self.slave, HasWaitingFiles.byEquality({ |
560 | |
561 | === modified file 'lpbuildd/tests/test_snap.py' |
562 | --- lpbuildd/tests/test_snap.py 2017-08-22 14:53:29 +0000 |
563 | +++ lpbuildd/tests/test_snap.py 2017-08-22 16:03:15 +0000 |
564 | @@ -4,9 +4,11 @@ |
565 | __metaclass__ = type |
566 | |
567 | import os |
568 | -import shutil |
569 | -import tempfile |
570 | |
571 | +from fixtures import ( |
572 | + EnvironmentVariable, |
573 | + TempDir, |
574 | + ) |
575 | from testtools import TestCase |
576 | |
577 | from lpbuildd.snap import ( |
578 | @@ -35,19 +37,16 @@ |
579 | """Run SnapBuildManager through its iteration steps.""" |
580 | def setUp(self): |
581 | super(TestSnapBuildManagerIteration, self).setUp() |
582 | - self.working_dir = tempfile.mkdtemp() |
583 | - self.addCleanup(lambda: shutil.rmtree(self.working_dir)) |
584 | + self.working_dir = self.useFixture(TempDir()).path |
585 | slave_dir = os.path.join(self.working_dir, "slave") |
586 | home_dir = os.path.join(self.working_dir, "home") |
587 | for dir in (slave_dir, home_dir): |
588 | os.mkdir(dir) |
589 | + self.useFixture(EnvironmentVariable("HOME", home_dir)) |
590 | self.slave = FakeSlave(slave_dir) |
591 | self.buildid = "123" |
592 | self.buildmanager = MockBuildManager(self.slave, self.buildid) |
593 | - self.buildmanager.home = home_dir |
594 | self.buildmanager._cachepath = self.slave._cachepath |
595 | - self.build_dir = os.path.join( |
596 | - home_dir, "build-%s" % self.buildid, "chroot-autobuild", "build") |
597 | |
598 | def getState(self): |
599 | """Retrieve build manager's state.""" |
600 | @@ -63,7 +62,10 @@ |
601 | "git_repository": "https://git.launchpad.dev/~example/+git/snap", |
602 | "git_path": "master", |
603 | } |
604 | + original_backend_name = self.buildmanager.backend_name |
605 | + self.buildmanager.backend_name = "fake" |
606 | self.buildmanager.initiate({}, "chroot.tar.gz", extra_args) |
607 | + self.buildmanager.backend_name = original_backend_name |
608 | |
609 | # Skip states that are done in DebianBuildManager to the state |
610 | # directly before BUILD_SNAP. |
611 | @@ -102,11 +104,8 @@ |
612 | with open(log_path, "w") as log: |
613 | log.write("I am a build log.") |
614 | |
615 | - output_dir = os.path.join(self.build_dir, "test-snap") |
616 | - os.makedirs(output_dir) |
617 | - snap_path = os.path.join(output_dir, "test-snap_0_all.snap") |
618 | - with open(snap_path, "w") as snap: |
619 | - snap.write("I am a snap package.") |
620 | + self.buildmanager.backend.add_file( |
621 | + "/build/test-snap/test-snap_0_all.snap", b"I am a snap package.") |
622 | |
623 | # After building the package, reap processes. |
624 | self.buildmanager.iterate(0) |
625 | @@ -148,14 +147,10 @@ |
626 | with open(log_path, "w") as log: |
627 | log.write("I am a build log.") |
628 | |
629 | - output_dir = os.path.join(self.build_dir, "test-snap") |
630 | - os.makedirs(output_dir) |
631 | - snap_path = os.path.join(output_dir, "test-snap_0_all.snap") |
632 | - with open(snap_path, "w") as snap: |
633 | - snap.write("I am a snap package.") |
634 | - manifest_path = os.path.join(output_dir, "test-snap_0_all.manifest") |
635 | - with open(manifest_path, "w") as manifest: |
636 | - manifest.write("I am a manifest.") |
637 | + self.buildmanager.backend.add_file( |
638 | + "/build/test-snap/test-snap_0_all.snap", b"I am a snap package.") |
639 | + self.buildmanager.backend.add_file( |
640 | + "/build/test-snap/test-snap_0_all.manifest", b"I am a manifest.") |
641 | |
642 | # After building the package, reap processes. |
643 | self.buildmanager.iterate(0) |
644 | |
645 | === modified file 'lpbuildd/tests/test_translationtemplatesbuildmanager.py' |
646 | --- lpbuildd/tests/test_translationtemplatesbuildmanager.py 2017-08-22 14:53:29 +0000 |
647 | +++ lpbuildd/tests/test_translationtemplatesbuildmanager.py 2017-08-22 16:03:15 +0000 |
648 | @@ -4,9 +4,11 @@ |
649 | __metaclass__ = type |
650 | |
651 | import os |
652 | -import shutil |
653 | -import tempfile |
654 | |
655 | +from fixtures import ( |
656 | + EnvironmentVariable, |
657 | + TempDir, |
658 | + ) |
659 | from testtools import TestCase |
660 | |
661 | from lpbuildd.tests.fakeslave import FakeSlave |
662 | @@ -35,16 +37,15 @@ |
663 | """Run TranslationTemplatesBuildManager through its iteration steps.""" |
664 | def setUp(self): |
665 | super(TestTranslationTemplatesBuildManagerIteration, self).setUp() |
666 | - self.working_dir = tempfile.mkdtemp() |
667 | - self.addCleanup(lambda: shutil.rmtree(self.working_dir)) |
668 | + self.working_dir = self.useFixture(TempDir()).path |
669 | slave_dir = os.path.join(self.working_dir, 'slave') |
670 | home_dir = os.path.join(self.working_dir, 'home') |
671 | for dir in (slave_dir, home_dir): |
672 | os.mkdir(dir) |
673 | + self.useFixture(EnvironmentVariable("HOME", home_dir)) |
674 | self.slave = FakeSlave(slave_dir) |
675 | self.buildid = '123' |
676 | self.buildmanager = MockBuildManager(self.slave, self.buildid) |
677 | - self.buildmanager.home = home_dir |
678 | self.chrootdir = os.path.join( |
679 | home_dir, 'build-%s' % self.buildid, 'chroot-autobuild') |
680 | |
681 | @@ -57,8 +58,11 @@ |
682 | url = 'lp:~my/branch' |
683 | # The build manager's iterate() kicks off the consecutive states |
684 | # after INIT. |
685 | + original_backend_name = self.buildmanager.backend_name |
686 | + self.buildmanager.backend_name = "fake" |
687 | self.buildmanager.initiate( |
688 | {}, 'chroot.tar.gz', {'series': 'xenial', 'branch_url': url}) |
689 | + self.buildmanager.backend_name = original_backend_name |
690 | |
691 | # Skip states that are done in DebianBuildManager to the state |
692 | # directly before INSTALL. |
693 | @@ -94,12 +98,9 @@ |
694 | self.assertFalse(self.slave.wasCalled('chrootFail')) |
695 | |
696 | outfile_path = os.path.join( |
697 | - self.chrootdir, self.buildmanager.home[1:], |
698 | - self.buildmanager._resultname) |
699 | - os.makedirs(os.path.dirname(outfile_path)) |
700 | - |
701 | - with open(outfile_path, 'w') as outfile: |
702 | - outfile.write("I am a template tarball. Seriously.") |
703 | + self.buildmanager.home, self.buildmanager._resultname) |
704 | + self.buildmanager.backend.add_file( |
705 | + outfile_path, b"I am a template tarball. Seriously.") |
706 | |
707 | # After generating templates, reap processes. |
708 | self.buildmanager.iterate(0) |
709 | @@ -169,7 +170,7 @@ |
710 | self.buildmanager.initiate( |
711 | {}, 'chroot.tar.gz', {'series': 'xenial', 'branch_url': url}) |
712 | |
713 | - # Skip states to the INSTALL state. |
714 | + # Skip states to the GENERATE state. |
715 | self.buildmanager._state = TranslationTemplatesBuildState.GENERATE |
716 | |
717 | # The buildmanager fails and reaps processes. |
718 | |
719 | === modified file 'lpbuildd/translationtemplates.py' |
720 | --- lpbuildd/translationtemplates.py 2015-05-11 05:39:25 +0000 |
721 | +++ lpbuildd/translationtemplates.py 2017-08-22 16:03:15 +0000 |
722 | @@ -64,12 +64,9 @@ |
723 | """Gather the results of the build and add them to the file cache.""" |
724 | # The file is inside the chroot, in the home directory of the buildd |
725 | # user. Should be safe to assume the home dirs are named identically. |
726 | - assert self.home.startswith('/'), "home directory must be absolute." |
727 | - |
728 | - path = os.path.join( |
729 | - self._chroot_path, self.home[1:], self._resultname) |
730 | - if os.access(path, os.F_OK): |
731 | - self._slave.addWaitingFile(path) |
732 | + path = os.path.join(self.home, self._resultname) |
733 | + if self.backend.path_exists(path): |
734 | + self.addWaitingFileFromBackend(path) |
735 | |
736 | def iterate_INSTALL(self, success): |
737 | """Installation was done.""" |