Merge lp:~blr/launchpad-buildd/snap_http_proxy into lp:launchpad-buildd
- snap_http_proxy
- Merge into trunk
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 |
Related bugs: |
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.
- 175. By Kit Randel
-
Add http_proxy to buildsnap args.
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}
> > + "@{host}
> > + username=
> > + password=
> > + host=self.
> > + port=self.
> > + 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.runSubProc
>
> > if self.branch is not None:
> > args.extend(
> > if self.git_repository is not None:
>
>
> --
>
> https:/
> You are the owner of lp:~blr/launchpad-buildd/snap_http_proxy.
>
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.
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.
- 188. By Kit Randel
-
Remove debugging print statement.
- 189. By Kit Randel
-
Sanitize proxy url in snap build logs.
Colin Watson (cjwatson) : | # |
- 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
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 |
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?