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
1=== modified file 'debian/changelog'
2--- debian/changelog 2018-01-15 10:08:55 +0000
3+++ debian/changelog 2018-02-04 00:20:53 +0000
4@@ -1,3 +1,13 @@
5+launchpad-buildd (159) UNRELEASED; urgency=medium
6+
7+ * Allow all snapd services in the policy-rc.d we install in LXD
8+ containers; for better or worse, snapd.postinst (via deb-systemd-invoke)
9+ won't start any of them, including snapd itself, if any of them is
10+ forbidden. Mask snapd.refresh.timer so that it doesn't cause trouble.
11+ * Allow optionally installing snapcraft as a snap (LP: #1737994).
12+
13+ -- Colin Watson <cjwatson@ubuntu.com> Fri, 02 Feb 2018 16:14:46 +0000
14+
15 launchpad-buildd (158) xenial; urgency=medium
16
17 [ Steve Langasek ]
18
19=== modified file 'lpbuildd/snap.py'
20--- lpbuildd/snap.py 2017-08-25 16:05:49 +0000
21+++ lpbuildd/snap.py 2018-02-04 00:20:53 +0000
22@@ -38,6 +38,7 @@
23 def initiate(self, files, chroot, extra_args):
24 """Initiate a build with a given set of files and chroot."""
25 self.name = extra_args["name"]
26+ self.channels = extra_args.get("channels", {})
27 self.branch = extra_args.get("branch")
28 self.git_repository = extra_args.get("git_repository")
29 self.git_path = extra_args.get("git_path")
30@@ -62,6 +63,16 @@
31 def doRunBuild(self):
32 """Run the process to build the snap."""
33 args = []
34+ known_snaps = ("core", "snapcraft")
35+ for snap in known_snaps:
36+ if snap in self.channels:
37+ args.extend(["--channel-%s" % snap, self.channels[snap]])
38+ unknown_snaps = set(self.channels) - set(known_snaps)
39+ if unknown_snaps:
40+ print(
41+ "Channels requested for unknown snaps: %s" %
42+ " ".join(sorted(unknown_snaps)),
43+ file=sys.stderr)
44 if self.proxy_url:
45 args.extend(["--proxy-url", self.proxy_url])
46 if self.revocation_endpoint:
47
48=== modified file 'lpbuildd/target/build_snap.py'
49--- lpbuildd/target/build_snap.py 2017-11-24 16:08:17 +0000
50+++ lpbuildd/target/build_snap.py 2018-02-04 00:20:53 +0000
51@@ -48,6 +48,14 @@
52 @classmethod
53 def add_arguments(cls, parser):
54 super(BuildSnap, cls).add_arguments(parser)
55+ parser.add_argument(
56+ "--channel-core", metavar="CHANNEL",
57+ help="install core snap from CHANNEL")
58+ parser.add_argument(
59+ "--channel-snapcraft", metavar="CHANNEL",
60+ help=(
61+ "install snapcraft as a snap from CHANNEL rather than as a "
62+ ".deb"))
63 build_from_group = parser.add_mutually_exclusive_group(required=True)
64 build_from_group.add_argument(
65 "--branch", metavar="BRANCH", help="build from this Bazaar branch")
66@@ -100,7 +108,7 @@
67
68 def install(self):
69 logger.info("Running install phase...")
70- deps = ["snapcraft"]
71+ deps = []
72 if self.args.backend == "lxd":
73 # udev is installed explicitly to work around
74 # https://bugs.launchpad.net/snapd/+bug/1731519.
75@@ -113,7 +121,17 @@
76 deps.append("git")
77 if self.args.proxy_url:
78 deps.extend(["python3", "socat"])
79+ if not self.args.channel_snapcraft:
80+ deps.append("snapcraft")
81 self.backend.run(["apt-get", "-y", "install"] + deps)
82+ if self.args.channel_core:
83+ self.backend.run(
84+ ["snap", "install",
85+ "--channel=%s" % self.args.channel_core, "core"])
86+ if self.args.channel_snapcraft:
87+ self.backend.run(
88+ ["snap", "install", "--classic",
89+ "--channel=%s" % self.args.channel_snapcraft, "snapcraft"])
90 if self.args.proxy_url:
91 self.backend.copy_in(
92 os.path.join(self.slavebin, "snap-git-proxy"),
93
94=== modified file 'lpbuildd/target/lxd.py'
95--- lpbuildd/target/lxd.py 2017-11-13 15:18:07 +0000
96+++ lpbuildd/target/lxd.py 2018-02-04 00:20:53 +0000
97@@ -51,7 +51,7 @@
98 -*) shift ;;
99 systemd-udevd|systemd-udevd.service|udev|udev.service)
100 exit 0 ;;
101- snapd|snapd.socket|snapd.service)
102+ snapd|snapd.*)
103 exit 0 ;;
104 *)
105 echo "Not running services in chroot."
106@@ -419,6 +419,14 @@
107 no_cdn_file.name,
108 "/etc/systemd/system/snapd.service.d/no-cdn.conf")
109
110+ # Refreshing snaps from a timer unit during a build isn't
111+ # appropriate. Mask this, but manually so that we don't depend on
112+ # systemctl existing. This relies on /etc/systemd/system/ having
113+ # been created above.
114+ self.run(
115+ ["ln", "-s", "/dev/null",
116+ "/etc/systemd/system/snapd.refresh.timer"])
117+
118 def run(self, args, cwd=None, env=None, input_text=None, get_output=False,
119 echo=False, **kwargs):
120 """See `Backend`."""
121
122=== modified file 'lpbuildd/target/tests/test_build_snap.py'
123--- lpbuildd/target/tests/test_build_snap.py 2017-11-24 16:08:17 +0000
124+++ lpbuildd/target/tests/test_build_snap.py 2018-02-04 00:20:53 +0000
125@@ -54,6 +54,12 @@
126 super(RanAptGet, self).__init__(["apt-get", "-y"] + list(args))
127
128
129+class RanSnap(RanCommand):
130+
131+ def __init__(self, *args):
132+ super(RanSnap, self).__init__(["snap"] + list(args))
133+
134+
135 class RanBuildCommand(RanCommand):
136
137 def __init__(self, args, cwd="/build", **kwargs):
138@@ -111,7 +117,7 @@
139 build_snap = parse_args(args=args).operation
140 build_snap.install()
141 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
142- RanAptGet("install", "snapcraft", "bzr"),
143+ RanAptGet("install", "bzr", "snapcraft"),
144 ]))
145
146 def test_install_git(self):
147@@ -123,7 +129,7 @@
148 build_snap = parse_args(args=args).operation
149 build_snap.install()
150 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
151- RanAptGet("install", "snapcraft", "git"),
152+ RanAptGet("install", "git", "snapcraft"),
153 ]))
154
155 def test_install_proxy(self):
156@@ -143,12 +149,27 @@
157 os.fchmod(proxy_script.fileno(), 0o755)
158 build_snap.install()
159 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
160- RanAptGet("install", "snapcraft", "git", "python3", "socat"),
161+ RanAptGet("install", "git", "python3", "socat", "snapcraft"),
162 ]))
163 self.assertEqual(
164 (b"proxy script\n", stat.S_IFREG | 0o755),
165 build_snap.backend.backend_fs["/usr/local/bin/snap-git-proxy"])
166
167+ def test_install_channels(self):
168+ args = [
169+ "buildsnap",
170+ "--backend=fake", "--series=xenial", "--arch=amd64", "1",
171+ "--channel-core=candidate", "--channel-snapcraft=edge",
172+ "--branch", "lp:foo", "test-snap",
173+ ]
174+ build_snap = parse_args(args=args).operation
175+ build_snap.install()
176+ self.assertThat(build_snap.backend.run.calls, MatchesListwise([
177+ RanAptGet("install", "bzr"),
178+ RanSnap("install", "--channel=candidate", "core"),
179+ RanSnap("install", "--classic", "--channel=edge", "snapcraft"),
180+ ]))
181+
182 def test_repo_bzr(self):
183 args = [
184 "buildsnap",
185@@ -332,7 +353,7 @@
186 build_snap.backend.run = FakeRevisionID("42")
187 self.assertEqual(0, build_snap.run())
188 self.assertThat(build_snap.backend.run.calls, MatchesAll(
189- AnyMatch(RanAptGet("install", "snapcraft", "bzr")),
190+ AnyMatch(RanAptGet("install", "bzr", "snapcraft")),
191 AnyMatch(RanBuildCommand(
192 ["bzr", "branch", "lp:foo", "test-snap"])),
193 AnyMatch(RanBuildCommand(
194
195=== modified file 'lpbuildd/target/tests/test_lxd.py'
196--- lpbuildd/target/tests/test_lxd.py 2017-11-13 15:18:07 +0000
197+++ lpbuildd/target/tests/test_lxd.py 2018-02-04 00:20:53 +0000
198@@ -254,9 +254,14 @@
199 lxc +
200 ["mknod", "-m", "0660", "/dev/loop%d" % minor,
201 "b", "7", str(minor)]))
202- expected_args.append(
203- Equals(
204- lxc + ["mkdir", "-p", "/etc/systemd/system/snapd.service.d"]))
205+ expected_args.extend([
206+ Equals(
207+ lxc + ["mkdir", "-p", "/etc/systemd/system/snapd.service.d"]),
208+ Equals(
209+ lxc +
210+ ["ln", "-s", "/dev/null",
211+ "/etc/systemd/system/snapd.refresh.timer"]),
212+ ])
213 self.assertThat(
214 [proc._args["args"] for proc in processes_fixture.procs],
215 MatchesListwise(expected_args))

Subscribers

People subscribed via source and target branches

to all changes: