Merge lp:~blr/launchpad-buildd/snap_http_proxy into lp:launchpad-buildd

Proposed by Kit Randel
Status: Merged
Merged at revision: 190
Proposed branch: lp:~blr/launchpad-buildd/snap_http_proxy
Merge into: lp:launchpad-buildd
Diff against target: 207 lines (+73/-11)
4 files modified
buildsnap (+54/-6)
lpbuildd/slave.py (+8/-4)
lpbuildd/snap.py (+10/-0)
lpbuildd/tests/test_snap.py (+1/-1)
To merge this branch: bzr merge lp:~blr/launchpad-buildd/snap_http_proxy
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
William Grant Pending
Review via email: mp+273355@code.launchpad.net

Commit message

Add http_proxy to buildsnap args.

Description of the change

Add http_proxy environment variable to buildsnap args, providing time limited external access. This branch also factors out buildsnap into distinct repo, pull, build and token revocation phases.

To post a comment you must log in.
175. By Kit Randel

Add http_proxy to buildsnap args.

Revision history for this message
Colin Watson (cjwatson) wrote :

It sounds like the direction we're going is indeed going to be to provide external access for the whole duration of the build, but could you please get in touch with Martin Albisetti to confirm that that's definitely what we have to do rather than separating out the pull phase and providing external access only to that as we'd previously intended?

review: Approve
Revision history for this message
Kit Randel (blr) wrote :

Thanks Colin, I'll catch up with Martin and make those changes.

On Mon, Oct 5, 2015 at 11:50 AM Colin Watson <email address hidden> wrote:

> Review: Approve
>
> It sounds like the direction we're going is indeed going to be to provide
> external access for the whole duration of the build, but could you please
> get in touch with Martin Albisetti to confirm that that's definitely what
> we have to do rather than separating out the pull phase and providing
> external access only to that as we'd previously intended?
>
> Diff comments:
>
> > === modified file 'lpbuildd/snap.py'
> > --- lpbuildd/snap.py 2015-07-31 11:54:07 +0000
> > +++ lpbuildd/snap.py 2015-10-04 22:12:07 +0000
> > @@ -52,6 +56,15 @@
> > "--build-id", self._buildid,
> > "--arch", self.arch_tag,
> > ]
> > + if self.proxy_token:
>
> Maybe worth checking here that all the necessary arguments were passed,
> just in case.
>
> > + proxy_env = (
> > + "http_proxy=http://{username}:{password}"
> > + "@{host}:{port}".format(
> > + username=self.build_cookie,
> > + password=self.proxy_token,
> > + host=self.proxy_host,
> > + port=self.proxy_port))
> > + args.insert(0, proxy_env)
>
> Rather than relying on shell parsing of environment variable prefixes to
> the command, could you please instead add an env=None keyword argument to
> runSubProcess, defaulting to os.environ if None, so that you can then do
> something like:
>
> env = dict(os.environ)
> if condition:
> env["http_proxy"] = blah
> ...
> self.runSubProcess(self.build_snap_path, args, env=env)
>
> > if self.branch is not None:
> > args.extend(["--branch", self.branch])
> > if self.git_repository is not None:
>
>
> --
>
> https://code.launchpad.net/~blr/launchpad-buildd/snap_http_proxy/+merge/273355
> You are the owner of lp:~blr/launchpad-buildd/snap_http_proxy.
>

Revision history for this message
William Grant (wgrant) wrote :

Rather than encoding in launchpad-buildd the knowledge that the username is the build cookie, I think it would make more sense for buildd-manager to simply pass in the full URL.

176. By Kit Randel

* Pass env to runSubProcess.
* Expect proxy_url in build extra_args, rather than proxy_username, proxy_password, proxy_host and proxy_port.

177. By Kit Randel

* Add env (os.environ) kwarg to runSubProcess.
* Fix broken os.environ set.
* Fix associated snap test.

178. By Kit Randel

* Pass proxy_url as argument to snapcraft script.
* Add pull phase to snapcraft builder.

179. By Kit Randel

Merge devel.

180. By Kit Randel

Correct buildsnap proxy-url option.

181. By Kit Randel

Move repo collect into distinct phase.

182. By Kit Randel

Add doctring for repo.

183. By Kit Randel

Add debugging.

184. By Kit Randel

Add token revocation.

185. By Kit Randel

Reset ssl_verify.

186. By Kit Randel

Remove debugging.

187. By Kit Randel

Move revoke_token to finally block.

Revision history for this message
Colin Watson (cjwatson) wrote :

The auth token logging issue mentioned in comments must be fixed, but aside from that it's just minor adjustments and is fine to land. Thanks.

review: Needs Fixing
188. By Kit Randel

Remove debugging print statement.

189. By Kit Randel

Sanitize proxy url in snap build logs.

Revision history for this message
Colin Watson (cjwatson) :
review: Approve
190. By Kit Randel

Set https_proxy envvar.

191. By Kit Randel

Ensure token revocation is conditioned on presense of key in extra_args.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildsnap'
2--- buildsnap 2015-09-23 22:06:16 +0000
3+++ buildsnap 2016-02-05 00:18:10 +0000
4@@ -8,11 +8,14 @@
5
6 __metaclass__ = type
7
8+import base64
9 from optparse import OptionParser
10 import os
11 import subprocess
12 import sys
13 import traceback
14+import urllib2
15+from urlparse import urlparse
16
17 from lpbuildd.util import (
18 set_personality,
19@@ -85,6 +88,7 @@
20 self.chroot(["/bin/sh", "-c", command], echo=echo)
21
22 def install(self):
23+ print("Running install phase...")
24 deps = ["snapcraft"]
25 if self.options.branch is not None:
26 deps.append("bzr")
27@@ -92,10 +96,15 @@
28 deps.append("git")
29 self.chroot(["apt-get", "-y", "install"] + deps)
30
31- def build(self):
32+ def repo(self):
33+ """Collect git or bzr branch."""
34+ print("Running repo phase...")
35 if self.options.branch is not None:
36- self.run_build_command([
37- "bzr", "branch", self.options.branch, self.name])
38+ self.run_build_command(['ls', '/build'])
39+ cmd = ["bzr", "branch", self.options.branch, self.name]
40+ if not self.ssl_verify:
41+ cmd.insert(1, "-Ossl.cert_reqs=none")
42+ self.run_build_command(cmd)
43 else:
44 assert self.options.git_repository is not None
45 assert self.options.git_path is not None
46@@ -107,9 +116,40 @@
47 "git", "clone", "-b", self.options.git_path,
48 self.options.git_repository, self.name],
49 env=env)
50- self.run_build_command(
51- ["snapcraft", "assemble"], path=os.path.join("/build", self.name),
52- env={"SNAPCRAFT_LOCAL_SOURCES": "1"})
53+
54+ def pull(self):
55+ """Run pull phase."""
56+ print("Running pull phase...")
57+ env = {"SNAPCRAFT_LOCAL_SOURCES": "1"}
58+ if self.options.proxy_url:
59+ env["http_proxy"] = self.options.proxy_url
60+ https_url = self.options.proxy_url.replace('http://', 'https://')
61+ env["https_proxy"] = https_url
62+ self.run_build_command(
63+ ["snapcraft", "pull"],
64+ path=os.path.join("/build", self.name),
65+ env=env)
66+
67+ def build(self):
68+ """Run all build, stage and snap phases."""
69+ print("Running build phase...")
70+ self.run_build_command(
71+ ["snapcraft", "all"], path=os.path.join("/build", self.name))
72+
73+ def revoke_token(self):
74+ """Revoke builder proxy token."""
75+ print("Revoking proxy token...")
76+ url = urlparse(self.options.proxy_url)
77+ auth = '{}:{}'.format(url.username, url.password)
78+ headers = {
79+ 'Authorization': 'Basic {}'.format(base64.b64encode(auth))
80+ }
81+ req = urllib2.Request(self.options.revocation_endpoint, None, headers)
82+ req.get_method = lambda: 'DELETE'
83+ try:
84+ urllib2.urlopen(req)
85+ except urllib2.HTTPError:
86+ print('Unable to revoke token for %s' % url.username)
87
88
89 def main():
90@@ -125,6 +165,9 @@
91 parser.add_option(
92 "--git-path", metavar="REF-PATH",
93 help="build from this ref path in REPOSITORY")
94+ parser.add_option("--proxy-url", help="builder proxy url")
95+ parser.add_option("--revocation-endpoint",
96+ help="builder proxy token revocation endpoint")
97 options, args = parser.parse_args()
98 if (options.git_repository is None) != (options.git_path is None):
99 parser.error(
100@@ -143,10 +186,15 @@
101 traceback.print_exc()
102 return RETCODE_FAILURE_INSTALL
103 try:
104+ builder.repo()
105+ builder.pull()
106 builder.build()
107 except Exception:
108 traceback.print_exc()
109 return RETCODE_FAILURE_BUILD
110+ finally:
111+ if options.revocation_endpoint is not None:
112+ builder.revoke_token()
113 return RETCODE_SUCCESS
114
115
116
117=== modified file 'lpbuildd/slave.py'
118--- lpbuildd/slave.py 2015-11-04 13:35:36 +0000
119+++ lpbuildd/slave.py 2016-02-05 00:18:10 +0000
120@@ -123,7 +123,11 @@
121 self.home = os.environ['HOME']
122 self.abort_timeout = 120
123
124- def runSubProcess(self, command, args, iterate=None):
125+ @property
126+ def needs_sanitized_logs(self):
127+ return self.is_archive_private
128+
129+ def runSubProcess(self, command, args, iterate=None, env=None):
130 """Run a sub process capturing the results in the log."""
131 if iterate is None:
132 iterate = self.iterate
133@@ -131,7 +135,7 @@
134 self._slave.log("RUN: %s %r\n" % (command, args))
135 childfds = {0: devnull.fileno(), 1: "r", 2: "r"}
136 self._reactor.spawnProcess(
137- self._subprocess, command, args, env=os.environ,
138+ self._subprocess, command, args, env=env,
139 path=self.home, childFDs=childfds)
140
141 def doUnpack(self):
142@@ -165,7 +169,7 @@
143
144 # Sanitize the URLs in the buildlog file if this is a build
145 # in a private archive.
146- if self.is_archive_private:
147+ if self.needs_sanitized_logs:
148 self._slave.sanitizeBuildlog(self._slave.cachePath("buildlog"))
149
150 def doMounting(self):
151@@ -492,7 +496,7 @@
152 if rlog is not None:
153 rlog.close()
154
155- if self.manager.is_archive_private:
156+ if self.manager.needs_sanitized_logs:
157 # This is a build in a private archive. We need to scrub
158 # the URLs contained in the buildlog excerpt in order to
159 # avoid leaking passwords.
160
161=== modified file 'lpbuildd/snap.py'
162--- lpbuildd/snap.py 2015-07-31 11:54:07 +0000
163+++ lpbuildd/snap.py 2016-02-05 00:18:10 +0000
164@@ -31,6 +31,10 @@
165 super(SnapBuildManager, self).__init__(slave, buildid, **kwargs)
166 self.build_snap_path = os.path.join(self._slavebin, "buildsnap")
167
168+ @property
169+ def needs_sanitized_logs(self):
170+ return True
171+
172 def initiate(self, files, chroot, extra_args):
173 """Initiate a build with a given set of files and chroot."""
174 self.build_path = get_build_path(
175@@ -42,6 +46,8 @@
176 self.branch = extra_args.get("branch")
177 self.git_repository = extra_args.get("git_repository")
178 self.git_path = extra_args.get("git_path")
179+ self.proxy_url = extra_args.get("proxy_url")
180+ self.revocation_endpoint = extra_args.get("revocation_endpoint")
181
182 super(SnapBuildManager, self).initiate(files, chroot, extra_args)
183
184@@ -52,6 +58,10 @@
185 "--build-id", self._buildid,
186 "--arch", self.arch_tag,
187 ]
188+ if self.proxy_url:
189+ args.extend(["--proxy-url", self.proxy_url])
190+ if self.revocation_endpoint:
191+ args.extend(["--revocation-endpoint", self.revocation_endpoint])
192 if self.branch is not None:
193 args.extend(["--branch", self.branch])
194 if self.git_repository is not None:
195
196=== modified file 'lpbuildd/tests/test_snap.py'
197--- lpbuildd/tests/test_snap.py 2015-07-31 11:54:07 +0000
198+++ lpbuildd/tests/test_snap.py 2016-02-05 00:18:10 +0000
199@@ -22,7 +22,7 @@
200 self.commands = []
201 self.iterators = []
202
203- def runSubProcess(self, path, command, iterate=None):
204+ def runSubProcess(self, path, command, iterate=None, env=None):
205 self.commands.append([path] + command)
206 if iterate is None:
207 iterate = self.iterate

Subscribers

People subscribed via source and target branches