Merge lp:~cjwatson/launchpad-buildd/snapception into lp:launchpad-buildd

Proposed by Colin Watson
Status: Merged
Merged at revision: 327
Proposed branch: lp:~cjwatson/launchpad-buildd/snapception
Merge into: lp:launchpad-buildd
Diff against target: 215 lines (+82/-9)
6 files modified
debian/changelog (+10/-0)
lpbuildd/snap.py (+11/-0)
lpbuildd/target/build_snap.py (+19/-1)
lpbuildd/target/lxd.py (+9/-1)
lpbuildd/target/tests/test_build_snap.py (+25/-4)
lpbuildd/target/tests/test_lxd.py (+8/-3)
To merge this branch: bzr merge lp:~cjwatson/launchpad-buildd/snapception
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+337126@code.launchpad.net

Commit message

Allow optionally installing snapcraft as a snap.

Description of the change

This is controlled by an optional "channels" key in the build arguments, which takes a dict mapping snap names to channel names. At present anything other than "core" and "snapcraft" will cause a warning but otherwise be ignored, but I chose this structure so that it's reasonably easy to extend in future (e.g. for base snaps).

In the process, I noticed that snapd wasn't actually being started in LXD-based builds due to details of how the systemd services are started in snapd.postinst, which definitely wasn't intended and is probably a regression, so I fixed that as otherwise "snap install" obviously doesn't work.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2018-01-15 10:08:55 +0000
+++ debian/changelog 2018-02-04 00:20:53 +0000
@@ -1,3 +1,13 @@
1launchpad-buildd (159) UNRELEASED; urgency=medium
2
3 * Allow all snapd services in the policy-rc.d we install in LXD
4 containers; for better or worse, snapd.postinst (via deb-systemd-invoke)
5 won't start any of them, including snapd itself, if any of them is
6 forbidden. Mask snapd.refresh.timer so that it doesn't cause trouble.
7 * Allow optionally installing snapcraft as a snap (LP: #1737994).
8
9 -- Colin Watson <cjwatson@ubuntu.com> Fri, 02 Feb 2018 16:14:46 +0000
10
1launchpad-buildd (158) xenial; urgency=medium11launchpad-buildd (158) xenial; urgency=medium
212
3 [ Steve Langasek ]13 [ Steve Langasek ]
414
=== modified file 'lpbuildd/snap.py'
--- lpbuildd/snap.py 2017-08-25 16:05:49 +0000
+++ lpbuildd/snap.py 2018-02-04 00:20:53 +0000
@@ -38,6 +38,7 @@
38 def initiate(self, files, chroot, extra_args):38 def initiate(self, files, chroot, extra_args):
39 """Initiate a build with a given set of files and chroot."""39 """Initiate a build with a given set of files and chroot."""
40 self.name = extra_args["name"]40 self.name = extra_args["name"]
41 self.channels = extra_args.get("channels", {})
41 self.branch = extra_args.get("branch")42 self.branch = extra_args.get("branch")
42 self.git_repository = extra_args.get("git_repository")43 self.git_repository = extra_args.get("git_repository")
43 self.git_path = extra_args.get("git_path")44 self.git_path = extra_args.get("git_path")
@@ -62,6 +63,16 @@
62 def doRunBuild(self):63 def doRunBuild(self):
63 """Run the process to build the snap."""64 """Run the process to build the snap."""
64 args = []65 args = []
66 known_snaps = ("core", "snapcraft")
67 for snap in known_snaps:
68 if snap in self.channels:
69 args.extend(["--channel-%s" % snap, self.channels[snap]])
70 unknown_snaps = set(self.channels) - set(known_snaps)
71 if unknown_snaps:
72 print(
73 "Channels requested for unknown snaps: %s" %
74 " ".join(sorted(unknown_snaps)),
75 file=sys.stderr)
65 if self.proxy_url:76 if self.proxy_url:
66 args.extend(["--proxy-url", self.proxy_url])77 args.extend(["--proxy-url", self.proxy_url])
67 if self.revocation_endpoint:78 if self.revocation_endpoint:
6879
=== modified file 'lpbuildd/target/build_snap.py'
--- lpbuildd/target/build_snap.py 2017-11-24 16:08:17 +0000
+++ lpbuildd/target/build_snap.py 2018-02-04 00:20:53 +0000
@@ -48,6 +48,14 @@
48 @classmethod48 @classmethod
49 def add_arguments(cls, parser):49 def add_arguments(cls, parser):
50 super(BuildSnap, cls).add_arguments(parser)50 super(BuildSnap, cls).add_arguments(parser)
51 parser.add_argument(
52 "--channel-core", metavar="CHANNEL",
53 help="install core snap from CHANNEL")
54 parser.add_argument(
55 "--channel-snapcraft", metavar="CHANNEL",
56 help=(
57 "install snapcraft as a snap from CHANNEL rather than as a "
58 ".deb"))
51 build_from_group = parser.add_mutually_exclusive_group(required=True)59 build_from_group = parser.add_mutually_exclusive_group(required=True)
52 build_from_group.add_argument(60 build_from_group.add_argument(
53 "--branch", metavar="BRANCH", help="build from this Bazaar branch")61 "--branch", metavar="BRANCH", help="build from this Bazaar branch")
@@ -100,7 +108,7 @@
100108
101 def install(self):109 def install(self):
102 logger.info("Running install phase...")110 logger.info("Running install phase...")
103 deps = ["snapcraft"]111 deps = []
104 if self.args.backend == "lxd":112 if self.args.backend == "lxd":
105 # udev is installed explicitly to work around113 # udev is installed explicitly to work around
106 # https://bugs.launchpad.net/snapd/+bug/1731519.114 # https://bugs.launchpad.net/snapd/+bug/1731519.
@@ -113,7 +121,17 @@
113 deps.append("git")121 deps.append("git")
114 if self.args.proxy_url:122 if self.args.proxy_url:
115 deps.extend(["python3", "socat"])123 deps.extend(["python3", "socat"])
124 if not self.args.channel_snapcraft:
125 deps.append("snapcraft")
116 self.backend.run(["apt-get", "-y", "install"] + deps)126 self.backend.run(["apt-get", "-y", "install"] + deps)
127 if self.args.channel_core:
128 self.backend.run(
129 ["snap", "install",
130 "--channel=%s" % self.args.channel_core, "core"])
131 if self.args.channel_snapcraft:
132 self.backend.run(
133 ["snap", "install", "--classic",
134 "--channel=%s" % self.args.channel_snapcraft, "snapcraft"])
117 if self.args.proxy_url:135 if self.args.proxy_url:
118 self.backend.copy_in(136 self.backend.copy_in(
119 os.path.join(self.slavebin, "snap-git-proxy"),137 os.path.join(self.slavebin, "snap-git-proxy"),
120138
=== modified file 'lpbuildd/target/lxd.py'
--- lpbuildd/target/lxd.py 2017-11-13 15:18:07 +0000
+++ lpbuildd/target/lxd.py 2018-02-04 00:20:53 +0000
@@ -51,7 +51,7 @@
51 -*) shift ;;51 -*) shift ;;
52 systemd-udevd|systemd-udevd.service|udev|udev.service)52 systemd-udevd|systemd-udevd.service|udev|udev.service)
53 exit 0 ;;53 exit 0 ;;
54 snapd|snapd.socket|snapd.service)54 snapd|snapd.*)
55 exit 0 ;;55 exit 0 ;;
56 *)56 *)
57 echo "Not running services in chroot."57 echo "Not running services in chroot."
@@ -419,6 +419,14 @@
419 no_cdn_file.name,419 no_cdn_file.name,
420 "/etc/systemd/system/snapd.service.d/no-cdn.conf")420 "/etc/systemd/system/snapd.service.d/no-cdn.conf")
421421
422 # Refreshing snaps from a timer unit during a build isn't
423 # appropriate. Mask this, but manually so that we don't depend on
424 # systemctl existing. This relies on /etc/systemd/system/ having
425 # been created above.
426 self.run(
427 ["ln", "-s", "/dev/null",
428 "/etc/systemd/system/snapd.refresh.timer"])
429
422 def run(self, args, cwd=None, env=None, input_text=None, get_output=False,430 def run(self, args, cwd=None, env=None, input_text=None, get_output=False,
423 echo=False, **kwargs):431 echo=False, **kwargs):
424 """See `Backend`."""432 """See `Backend`."""
425433
=== modified file 'lpbuildd/target/tests/test_build_snap.py'
--- lpbuildd/target/tests/test_build_snap.py 2017-11-24 16:08:17 +0000
+++ lpbuildd/target/tests/test_build_snap.py 2018-02-04 00:20:53 +0000
@@ -54,6 +54,12 @@
54 super(RanAptGet, self).__init__(["apt-get", "-y"] + list(args))54 super(RanAptGet, self).__init__(["apt-get", "-y"] + list(args))
5555
5656
57class RanSnap(RanCommand):
58
59 def __init__(self, *args):
60 super(RanSnap, self).__init__(["snap"] + list(args))
61
62
57class RanBuildCommand(RanCommand):63class RanBuildCommand(RanCommand):
5864
59 def __init__(self, args, cwd="/build", **kwargs):65 def __init__(self, args, cwd="/build", **kwargs):
@@ -111,7 +117,7 @@
111 build_snap = parse_args(args=args).operation117 build_snap = parse_args(args=args).operation
112 build_snap.install()118 build_snap.install()
113 self.assertThat(build_snap.backend.run.calls, MatchesListwise([119 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
114 RanAptGet("install", "snapcraft", "bzr"),120 RanAptGet("install", "bzr", "snapcraft"),
115 ]))121 ]))
116122
117 def test_install_git(self):123 def test_install_git(self):
@@ -123,7 +129,7 @@
123 build_snap = parse_args(args=args).operation129 build_snap = parse_args(args=args).operation
124 build_snap.install()130 build_snap.install()
125 self.assertThat(build_snap.backend.run.calls, MatchesListwise([131 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
126 RanAptGet("install", "snapcraft", "git"),132 RanAptGet("install", "git", "snapcraft"),
127 ]))133 ]))
128134
129 def test_install_proxy(self):135 def test_install_proxy(self):
@@ -143,12 +149,27 @@
143 os.fchmod(proxy_script.fileno(), 0o755)149 os.fchmod(proxy_script.fileno(), 0o755)
144 build_snap.install()150 build_snap.install()
145 self.assertThat(build_snap.backend.run.calls, MatchesListwise([151 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
146 RanAptGet("install", "snapcraft", "git", "python3", "socat"),152 RanAptGet("install", "git", "python3", "socat", "snapcraft"),
147 ]))153 ]))
148 self.assertEqual(154 self.assertEqual(
149 (b"proxy script\n", stat.S_IFREG | 0o755),155 (b"proxy script\n", stat.S_IFREG | 0o755),
150 build_snap.backend.backend_fs["/usr/local/bin/snap-git-proxy"])156 build_snap.backend.backend_fs["/usr/local/bin/snap-git-proxy"])
151157
158 def test_install_channels(self):
159 args = [
160 "buildsnap",
161 "--backend=fake", "--series=xenial", "--arch=amd64", "1",
162 "--channel-core=candidate", "--channel-snapcraft=edge",
163 "--branch", "lp:foo", "test-snap",
164 ]
165 build_snap = parse_args(args=args).operation
166 build_snap.install()
167 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
168 RanAptGet("install", "bzr"),
169 RanSnap("install", "--channel=candidate", "core"),
170 RanSnap("install", "--classic", "--channel=edge", "snapcraft"),
171 ]))
172
152 def test_repo_bzr(self):173 def test_repo_bzr(self):
153 args = [174 args = [
154 "buildsnap",175 "buildsnap",
@@ -332,7 +353,7 @@
332 build_snap.backend.run = FakeRevisionID("42")353 build_snap.backend.run = FakeRevisionID("42")
333 self.assertEqual(0, build_snap.run())354 self.assertEqual(0, build_snap.run())
334 self.assertThat(build_snap.backend.run.calls, MatchesAll(355 self.assertThat(build_snap.backend.run.calls, MatchesAll(
335 AnyMatch(RanAptGet("install", "snapcraft", "bzr")),356 AnyMatch(RanAptGet("install", "bzr", "snapcraft")),
336 AnyMatch(RanBuildCommand(357 AnyMatch(RanBuildCommand(
337 ["bzr", "branch", "lp:foo", "test-snap"])),358 ["bzr", "branch", "lp:foo", "test-snap"])),
338 AnyMatch(RanBuildCommand(359 AnyMatch(RanBuildCommand(
339360
=== modified file 'lpbuildd/target/tests/test_lxd.py'
--- lpbuildd/target/tests/test_lxd.py 2017-11-13 15:18:07 +0000
+++ lpbuildd/target/tests/test_lxd.py 2018-02-04 00:20:53 +0000
@@ -254,9 +254,14 @@
254 lxc +254 lxc +
255 ["mknod", "-m", "0660", "/dev/loop%d" % minor,255 ["mknod", "-m", "0660", "/dev/loop%d" % minor,
256 "b", "7", str(minor)]))256 "b", "7", str(minor)]))
257 expected_args.append(257 expected_args.extend([
258 Equals(258 Equals(
259 lxc + ["mkdir", "-p", "/etc/systemd/system/snapd.service.d"]))259 lxc + ["mkdir", "-p", "/etc/systemd/system/snapd.service.d"]),
260 Equals(
261 lxc +
262 ["ln", "-s", "/dev/null",
263 "/etc/systemd/system/snapd.refresh.timer"]),
264 ])
260 self.assertThat(265 self.assertThat(
261 [proc._args["args"] for proc in processes_fixture.procs],266 [proc._args["args"] for proc in processes_fixture.procs],
262 MatchesListwise(expected_args))267 MatchesListwise(expected_args))

Subscribers

People subscribed via source and target branches

to all changes: