Merge ~ines-almeida/launchpad:fetch-service-update-end-session into launchpad:master
- Git
- lp:~ines-almeida/launchpad
- fetch-service-update-end-session
- Merge into master
Proposed by
Ines Almeida
Status: | Merged |
---|---|
Approved by: | Ines Almeida |
Approved revision: | c55da58c037c6cb89c77787ae1c8b59c60eb3b68 |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | ~ines-almeida/launchpad:fetch-service-update-end-session |
Merge into: | launchpad:master |
Diff against target: |
413 lines (+131/-51) 4 files modified
lib/lp/buildmaster/builderproxy.py (+74/-39) lib/lp/buildmaster/interactor.py (+4/-0) lib/lp/buildmaster/tests/mock_workers.py (+12/-0) lib/lp/snappy/tests/test_snapbuildbehaviour.py (+41/-12) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jürgen Gmach | Approve | ||
Review via email: mp+465152@code.launchpad.net |
Commit message
Update how to keep track of session_id within a builder session
Description of the change
To post a comment you must log in.
Revision history for this message
Ines Almeida (ines-almeida) wrote : | # |
Revision history for this message
Jürgen Gmach (jugmac00) : | # |
Revision history for this message
Jürgen Gmach (jugmac00) : | # |
Revision history for this message
Ines Almeida (ines-almeida) wrote : | # |
Fixed the mypy issues and updated the logic to use the `use_fetch_service` flag directly from the builder proxy info. I still need to re-work a test, but this is now ready for review.
Revision history for this message
Jürgen Gmach (jugmac00) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/buildmaster/builderproxy.py b/lib/lp/buildmaster/builderproxy.py | |||
2 | index 1fc0d9b..a52ce06 100644 | |||
3 | --- a/lib/lp/buildmaster/builderproxy.py | |||
4 | +++ b/lib/lp/buildmaster/builderproxy.py | |||
5 | @@ -17,8 +17,9 @@ __all__ = [ | |||
6 | 17 | 17 | ||
7 | 18 | import base64 | 18 | import base64 |
8 | 19 | import os | 19 | import os |
9 | 20 | import re | ||
10 | 20 | import time | 21 | import time |
12 | 21 | from typing import Dict, Generator, Type | 22 | from typing import Optional |
13 | 22 | 23 | ||
14 | 23 | from twisted.internet import defer | 24 | from twisted.internet import defer |
15 | 24 | 25 | ||
16 | @@ -37,6 +38,10 @@ from lp.services.config import config | |||
17 | 37 | BUILD_METADATA_FILENAME_FORMAT = "{build_id}_metadata.json" | 38 | BUILD_METADATA_FILENAME_FORMAT = "{build_id}_metadata.json" |
18 | 38 | 39 | ||
19 | 39 | 40 | ||
20 | 41 | class ProxyServiceException(Exception): | ||
21 | 42 | pass | ||
22 | 43 | |||
23 | 44 | |||
24 | 40 | def _get_proxy_config(name): | 45 | def _get_proxy_config(name): |
25 | 41 | """Get a config item from builddmaster (current) or snappy (deprecated).""" | 46 | """Get a config item from builddmaster (current) or snappy (deprecated).""" |
26 | 42 | return getattr(config.builddmaster, name) or getattr(config.snappy, name) | 47 | return getattr(config.builddmaster, name) or getattr(config.snappy, name) |
27 | @@ -56,28 +61,23 @@ class BuilderProxyMixin: | |||
28 | 56 | build: BuildFarmJob | 61 | build: BuildFarmJob |
29 | 57 | _worker: BuilderWorker | 62 | _worker: BuilderWorker |
30 | 58 | 63 | ||
31 | 59 | def __init__(self, *args, **kwargs): | ||
32 | 60 | super().__init__(*args, **kwargs) | ||
33 | 61 | self._use_fetch_service = False | ||
34 | 62 | self._proxy_service = None | ||
35 | 63 | |||
36 | 64 | @defer.inlineCallbacks | 64 | @defer.inlineCallbacks |
37 | 65 | def startProxySession( | 65 | def startProxySession( |
38 | 66 | self, | 66 | self, |
39 | 67 | args: BuildArgs, | 67 | args: BuildArgs, |
40 | 68 | allow_internet: bool = True, | 68 | allow_internet: bool = True, |
41 | 69 | use_fetch_service: bool = False, | 69 | use_fetch_service: bool = False, |
45 | 70 | ) -> Generator[None, Dict[str, str], None]: | 70 | ): |
43 | 71 | |||
44 | 72 | self._use_fetch_service = use_fetch_service | ||
46 | 73 | 71 | ||
47 | 74 | if not allow_internet: | 72 | if not allow_internet: |
48 | 75 | return | 73 | return |
49 | 76 | 74 | ||
50 | 75 | proxy_service: IProxyService | ||
51 | 76 | |||
52 | 77 | if not use_fetch_service and _get_proxy_config("builder_proxy_host"): | 77 | if not use_fetch_service and _get_proxy_config("builder_proxy_host"): |
54 | 78 | proxy_service: Type[IProxyService] = BuilderProxy | 78 | proxy_service = BuilderProxy(worker=self._worker) |
55 | 79 | elif use_fetch_service and _get_proxy_config("fetch_service_host"): | 79 | elif use_fetch_service and _get_proxy_config("fetch_service_host"): |
57 | 80 | proxy_service = FetchService | 80 | proxy_service = FetchService(worker=self._worker) |
58 | 81 | 81 | ||
59 | 82 | # Append the fetch-service certificate to BuildArgs secrets. | 82 | # Append the fetch-service certificate to BuildArgs secrets. |
60 | 83 | if "secrets" not in args: | 83 | if "secrets" not in args: |
61 | @@ -91,10 +91,9 @@ class BuilderProxyMixin: | |||
62 | 91 | # non-production environments. | 91 | # non-production environments. |
63 | 92 | return | 92 | return |
64 | 93 | 93 | ||
67 | 94 | self._proxy_service = proxy_service( | 94 | session_data = yield proxy_service.startSession( |
68 | 95 | build_id=self.build.build_cookie, worker=self._worker | 95 | build_id=self.build.build_cookie |
69 | 96 | ) | 96 | ) |
70 | 97 | session_data = yield self._proxy_service.startSession() | ||
71 | 98 | 97 | ||
72 | 99 | args["proxy_url"] = session_data["proxy_url"] | 98 | args["proxy_url"] = session_data["proxy_url"] |
73 | 100 | args["revocation_endpoint"] = session_data["revocation_endpoint"] | 99 | args["revocation_endpoint"] = session_data["revocation_endpoint"] |
74 | @@ -115,34 +114,55 @@ class BuilderProxyMixin: | |||
75 | 115 | Sessions will be closed automatically within the Fetch Service after | 114 | Sessions will be closed automatically within the Fetch Service after |
76 | 116 | a certain amount of time configured by its charm (default 6 hours). | 115 | a certain amount of time configured by its charm (default 6 hours). |
77 | 117 | """ | 116 | """ |
78 | 118 | if not self._use_fetch_service: | ||
79 | 119 | # No cleanup needed for the builder proxy | ||
80 | 120 | return | ||
81 | 121 | 117 | ||
85 | 122 | if self._proxy_service is None: | 118 | proxy_info = yield self._worker.proxy_info() |
86 | 123 | # A session was never started. This can happen if the proxy configs | 119 | use_fetch_service = proxy_info.get("use_fetch_service") |
87 | 124 | # are not set (see `startProxySession`) | 120 | |
88 | 121 | if not use_fetch_service: | ||
89 | 122 | # No cleanup needed when not using the fetch service | ||
90 | 123 | # This is true both when we use the builder proxy and when we don't | ||
91 | 124 | # allow internet access to the builds. | ||
92 | 125 | return | 125 | return |
93 | 126 | 126 | ||
94 | 127 | proxy_service = FetchService(worker=self._worker) | ||
95 | 128 | |||
96 | 129 | # XXX ines-almeida 2024-04-30: Getting the session_id from the | ||
97 | 130 | # revocation_endpoint feels a little like going back and forwards | ||
98 | 131 | # given the revocation_endpoint is created on `startProxySession()`. | ||
99 | 132 | # Ideally, we would update `buildd` and `buildd-manager` to senf and | ||
100 | 133 | # retrieve the session ID directly (instead of having to parse it). | ||
101 | 134 | revocation_endpoint = proxy_info.get("revocation_endpoint") | ||
102 | 135 | session_id = proxy_service.extractSessionIDFromRevocationEndpoint( | ||
103 | 136 | revocation_endpoint | ||
104 | 137 | ) | ||
105 | 138 | |||
106 | 139 | if session_id is None: | ||
107 | 140 | raise ProxyServiceException( | ||
108 | 141 | "Could not parse the revocation endpoint fetched from buildd " | ||
109 | 142 | f"('{revocation_endpoint}') to get the fetch service " | ||
110 | 143 | "`session_id` used within the build." | ||
111 | 144 | ) | ||
112 | 145 | |||
113 | 127 | metadata_file_name = BUILD_METADATA_FILENAME_FORMAT.format( | 146 | metadata_file_name = BUILD_METADATA_FILENAME_FORMAT.format( |
114 | 128 | build_id=self.build.build_cookie | 147 | build_id=self.build.build_cookie |
115 | 129 | ) | 148 | ) |
116 | 130 | file_path = os.path.join(upload_path, metadata_file_name) | 149 | file_path = os.path.join(upload_path, metadata_file_name) |
119 | 131 | yield self._proxy_service.retrieveMetadataFromSession( | 150 | yield proxy_service.retrieveMetadataFromSession( |
120 | 132 | save_content_to=file_path | 151 | session_id=session_id, |
121 | 152 | save_content_to=file_path, | ||
122 | 133 | ) | 153 | ) |
123 | 134 | 154 | ||
125 | 135 | yield self._proxy_service.endSession() | 155 | yield proxy_service.endSession(session_id=session_id) |
126 | 136 | 156 | ||
127 | 137 | 157 | ||
128 | 138 | class IProxyService: | 158 | class IProxyService: |
129 | 139 | """Interface for Proxy Services - either FetchService or BuilderProxy.""" | 159 | """Interface for Proxy Services - either FetchService or BuilderProxy.""" |
130 | 140 | 160 | ||
132 | 141 | def __init__(self, build_id: str, worker: BuilderWorker): | 161 | def __init__(self, worker: BuilderWorker): |
133 | 142 | pass | 162 | pass |
134 | 143 | 163 | ||
135 | 144 | @defer.inlineCallbacks | 164 | @defer.inlineCallbacks |
137 | 145 | def startSession(self): | 165 | def startSession(self, build_id: str): |
138 | 146 | """Start a proxy session and request required | 166 | """Start a proxy session and request required |
139 | 147 | 167 | ||
140 | 148 | :returns: dictionary with an authenticated `proxy_url` for the builder | 168 | :returns: dictionary with an authenticated `proxy_url` for the builder |
141 | @@ -159,7 +179,7 @@ class BuilderProxy(IProxyService): | |||
142 | 159 | making API requests directly to the builder proxy control endpoint. | 179 | making API requests directly to the builder proxy control endpoint. |
143 | 160 | """ | 180 | """ |
144 | 161 | 181 | ||
146 | 162 | def __init__(self, build_id: str, worker: BuilderWorker): | 182 | def __init__(self, worker: BuilderWorker): |
147 | 163 | self.control_endpoint = _get_value_from_config( | 183 | self.control_endpoint = _get_value_from_config( |
148 | 164 | "builder_proxy_auth_api_endpoint" | 184 | "builder_proxy_auth_api_endpoint" |
149 | 165 | ) | 185 | ) |
150 | @@ -168,8 +188,6 @@ class BuilderProxy(IProxyService): | |||
151 | 168 | port=_get_value_from_config("builder_proxy_port"), | 188 | port=_get_value_from_config("builder_proxy_port"), |
152 | 169 | ) | 189 | ) |
153 | 170 | self.auth_header = self._getAuthHeader() | 190 | self.auth_header = self._getAuthHeader() |
154 | 171 | |||
155 | 172 | self.build_id = build_id | ||
156 | 173 | self.worker = worker | 191 | self.worker = worker |
157 | 174 | 192 | ||
158 | 175 | @staticmethod | 193 | @staticmethod |
159 | @@ -187,14 +205,14 @@ class BuilderProxy(IProxyService): | |||
160 | 187 | return b"Basic " + base64.b64encode(auth_string.encode("ASCII")) | 205 | return b"Basic " + base64.b64encode(auth_string.encode("ASCII")) |
161 | 188 | 206 | ||
162 | 189 | @defer.inlineCallbacks | 207 | @defer.inlineCallbacks |
164 | 190 | def startSession(self): | 208 | def startSession(self, build_id: str): |
165 | 191 | """Request a token from the builder proxy to be used by the builders. | 209 | """Request a token from the builder proxy to be used by the builders. |
166 | 192 | 210 | ||
167 | 193 | See IProxyService. | 211 | See IProxyService. |
168 | 194 | """ | 212 | """ |
169 | 195 | timestamp = int(time.time()) | 213 | timestamp = int(time.time()) |
170 | 196 | proxy_username = "{build_id}-{timestamp}".format( | 214 | proxy_username = "{build_id}-{timestamp}".format( |
172 | 197 | build_id=self.build_id, timestamp=timestamp | 215 | build_id=build_id, timestamp=timestamp |
173 | 198 | ) | 216 | ) |
174 | 199 | 217 | ||
175 | 200 | token = yield self.worker.process_pool.doWork( | 218 | token = yield self.worker.process_pool.doWork( |
176 | @@ -233,7 +251,7 @@ class FetchService(IProxyService): | |||
177 | 233 | RETRIEVE_METADATA_ENDPOINT = "{control_endpoint}/session/{session_id}" | 251 | RETRIEVE_METADATA_ENDPOINT = "{control_endpoint}/session/{session_id}" |
178 | 234 | END_SESSION_ENDPOINT = "{control_endpoint}/session/{session_id}" | 252 | END_SESSION_ENDPOINT = "{control_endpoint}/session/{session_id}" |
179 | 235 | 253 | ||
181 | 236 | def __init__(self, build_id: str, worker: BuilderWorker): | 254 | def __init__(self, worker: BuilderWorker): |
182 | 237 | self.control_endpoint = _get_value_from_config( | 255 | self.control_endpoint = _get_value_from_config( |
183 | 238 | "fetch_service_control_endpoint" | 256 | "fetch_service_control_endpoint" |
184 | 239 | ) | 257 | ) |
185 | @@ -242,10 +260,7 @@ class FetchService(IProxyService): | |||
186 | 242 | port=_get_value_from_config("fetch_service_port"), | 260 | port=_get_value_from_config("fetch_service_port"), |
187 | 243 | ) | 261 | ) |
188 | 244 | self.auth_header = self._getAuthHeader() | 262 | self.auth_header = self._getAuthHeader() |
189 | 245 | |||
190 | 246 | self.build_id = build_id | ||
191 | 247 | self.worker = worker | 263 | self.worker = worker |
192 | 248 | self.session_id = None | ||
193 | 249 | 264 | ||
194 | 250 | @staticmethod | 265 | @staticmethod |
195 | 251 | def _getAuthHeader(): | 266 | def _getAuthHeader(): |
196 | @@ -259,7 +274,7 @@ class FetchService(IProxyService): | |||
197 | 259 | return b"Basic " + base64.b64encode(auth_string.encode("ASCII")) | 274 | return b"Basic " + base64.b64encode(auth_string.encode("ASCII")) |
198 | 260 | 275 | ||
199 | 261 | @defer.inlineCallbacks | 276 | @defer.inlineCallbacks |
201 | 262 | def startSession(self): | 277 | def startSession(self, build_id: str): |
202 | 263 | """Requests a fetch service session and returns session information. | 278 | """Requests a fetch service session and returns session information. |
203 | 264 | 279 | ||
204 | 265 | See IProxyService. | 280 | See IProxyService. |
205 | @@ -290,8 +305,28 @@ class FetchService(IProxyService): | |||
206 | 290 | "revocation_endpoint": revocation_endpoint, | 305 | "revocation_endpoint": revocation_endpoint, |
207 | 291 | } | 306 | } |
208 | 292 | 307 | ||
209 | 308 | def extractSessionIDFromRevocationEndpoint( | ||
210 | 309 | self, revocation_endpoint: str | ||
211 | 310 | ) -> Optional[str]: | ||
212 | 311 | """Helper method to get the session_id out of the revocation | ||
213 | 312 | endpoint. | ||
214 | 313 | |||
215 | 314 | Example `revocation_endpoint`: | ||
216 | 315 | http://fetch-service.net:9999/session/913890402914ce3be9ffd4d0/token | ||
217 | 316 | |||
218 | 317 | Would return: 913890402914ce3be9ffd4d0 | ||
219 | 318 | """ | ||
220 | 319 | re_pattern = self.TOKEN_REVOCATION.format( | ||
221 | 320 | control_endpoint=self.control_endpoint, | ||
222 | 321 | session_id="(?P<session_id>.*)", | ||
223 | 322 | ) | ||
224 | 323 | match = re.match(re_pattern, revocation_endpoint) | ||
225 | 324 | return match["session_id"] if match else None | ||
226 | 325 | |||
227 | 293 | @defer.inlineCallbacks | 326 | @defer.inlineCallbacks |
229 | 294 | def retrieveMetadataFromSession(self, save_content_to: str): | 327 | def retrieveMetadataFromSession( |
230 | 328 | self, session_id: str, save_content_to: str | ||
231 | 329 | ): | ||
232 | 295 | """Make request to retrieve metadata from the current session. | 330 | """Make request to retrieve metadata from the current session. |
233 | 296 | 331 | ||
234 | 297 | Data is stored directly into a file whose path is `save_content_to` | 332 | Data is stored directly into a file whose path is `save_content_to` |
235 | @@ -300,7 +335,7 @@ class FetchService(IProxyService): | |||
236 | 300 | """ | 335 | """ |
237 | 301 | url = self.RETRIEVE_METADATA_ENDPOINT.format( | 336 | url = self.RETRIEVE_METADATA_ENDPOINT.format( |
238 | 302 | control_endpoint=self.control_endpoint, | 337 | control_endpoint=self.control_endpoint, |
240 | 303 | session_id=self.session_id, | 338 | session_id=session_id, |
241 | 304 | ) | 339 | ) |
242 | 305 | yield self.worker.process_pool.doWork( | 340 | yield self.worker.process_pool.doWork( |
243 | 306 | RetrieveFetchServiceSessionCommand, | 341 | RetrieveFetchServiceSessionCommand, |
244 | @@ -310,14 +345,14 @@ class FetchService(IProxyService): | |||
245 | 310 | ) | 345 | ) |
246 | 311 | 346 | ||
247 | 312 | @defer.inlineCallbacks | 347 | @defer.inlineCallbacks |
249 | 313 | def endSession(self): | 348 | def endSession(self, session_id: str): |
250 | 314 | """End the proxy session and do any cleanup needed. | 349 | """End the proxy session and do any cleanup needed. |
251 | 315 | 350 | ||
252 | 316 | :raises: RequestException if request to Fetch Service fails | 351 | :raises: RequestException if request to Fetch Service fails |
253 | 317 | """ | 352 | """ |
254 | 318 | url = self.END_SESSION_ENDPOINT.format( | 353 | url = self.END_SESSION_ENDPOINT.format( |
255 | 319 | control_endpoint=self.control_endpoint, | 354 | control_endpoint=self.control_endpoint, |
257 | 320 | session_id=self.session_id, | 355 | session_id=session_id, |
258 | 321 | ) | 356 | ) |
259 | 322 | yield self.worker.process_pool.doWork( | 357 | yield self.worker.process_pool.doWork( |
260 | 323 | EndFetchServiceSessionCommand, | 358 | EndFetchServiceSessionCommand, |
261 | diff --git a/lib/lp/buildmaster/interactor.py b/lib/lp/buildmaster/interactor.py | |||
262 | index dfcc86b..9bf1a71 100644 | |||
263 | --- a/lib/lp/buildmaster/interactor.py | |||
264 | +++ b/lib/lp/buildmaster/interactor.py | |||
265 | @@ -209,6 +209,10 @@ class BuilderWorker: | |||
266 | 209 | """Echo the arguments back.""" | 209 | """Echo the arguments back.""" |
267 | 210 | return self._with_timeout(self._server.callRemote("echo", *args)) | 210 | return self._with_timeout(self._server.callRemote("echo", *args)) |
268 | 211 | 211 | ||
269 | 212 | def proxy_info(self): | ||
270 | 213 | """Return the details for the proxy used by the manager.""" | ||
271 | 214 | return self._with_timeout(self._server.callRemote("proxy_info")) | ||
272 | 215 | |||
273 | 212 | def info(self): | 216 | def info(self): |
274 | 213 | """Return the protocol version and the builder methods supported.""" | 217 | """Return the protocol version and the builder methods supported.""" |
275 | 214 | return self._with_timeout(self._server.callRemote("info")) | 218 | return self._with_timeout(self._server.callRemote("info")) |
276 | diff --git a/lib/lp/buildmaster/tests/mock_workers.py b/lib/lp/buildmaster/tests/mock_workers.py | |||
277 | index a880a9a..5f5563b 100644 | |||
278 | --- a/lib/lp/buildmaster/tests/mock_workers.py | |||
279 | +++ b/lib/lp/buildmaster/tests/mock_workers.py | |||
280 | @@ -151,6 +151,18 @@ class OkWorker: | |||
281 | 151 | self.call_log.append("info") | 151 | self.call_log.append("info") |
282 | 152 | return defer.succeed(("1.0", self.arch_tag, "binarypackage")) | 152 | return defer.succeed(("1.0", self.arch_tag, "binarypackage")) |
283 | 153 | 153 | ||
284 | 154 | def proxy_info(self): | ||
285 | 155 | self.call_log.append("proxy_info") | ||
286 | 156 | return defer.succeed( | ||
287 | 157 | { | ||
288 | 158 | "revocation_endpoint": ( | ||
289 | 159 | "http://fetch-service.test:9999/session/" | ||
290 | 160 | "9138904ce3be9ffd4d0/token" | ||
291 | 161 | ), | ||
292 | 162 | "use_fetch_service": False, | ||
293 | 163 | } | ||
294 | 164 | ) | ||
295 | 165 | |||
296 | 154 | def resume(self): | 166 | def resume(self): |
297 | 155 | self.call_log.append("resume") | 167 | self.call_log.append("resume") |
298 | 156 | return defer.succeed(("", "", 0)) | 168 | return defer.succeed(("", "", 0)) |
299 | diff --git a/lib/lp/snappy/tests/test_snapbuildbehaviour.py b/lib/lp/snappy/tests/test_snapbuildbehaviour.py | |||
300 | index 81d6926..cb2269b 100644 | |||
301 | --- a/lib/lp/snappy/tests/test_snapbuildbehaviour.py | |||
302 | +++ b/lib/lp/snappy/tests/test_snapbuildbehaviour.py | |||
303 | @@ -10,6 +10,7 @@ import time | |||
304 | 10 | import uuid | 10 | import uuid |
305 | 11 | from datetime import datetime | 11 | from datetime import datetime |
306 | 12 | from textwrap import dedent | 12 | from textwrap import dedent |
307 | 13 | from unittest.mock import MagicMock | ||
308 | 13 | from urllib.parse import urlsplit | 14 | from urllib.parse import urlsplit |
309 | 14 | 15 | ||
310 | 15 | import fixtures | 16 | import fixtures |
311 | @@ -40,7 +41,6 @@ from lp.app.enums import InformationType | |||
312 | 40 | from lp.archivepublisher.interfaces.archivegpgsigningkey import ( | 41 | from lp.archivepublisher.interfaces.archivegpgsigningkey import ( |
313 | 41 | IArchiveGPGSigningKey, | 42 | IArchiveGPGSigningKey, |
314 | 42 | ) | 43 | ) |
315 | 43 | from lp.buildmaster.builderproxy import BuilderProxy | ||
316 | 44 | from lp.buildmaster.enums import BuildBaseImageType, BuildStatus | 44 | from lp.buildmaster.enums import BuildBaseImageType, BuildStatus |
317 | 45 | from lp.buildmaster.interactor import shut_down_default_process_pool | 45 | from lp.buildmaster.interactor import shut_down_default_process_pool |
318 | 46 | from lp.buildmaster.interfaces.builder import CannotBuild | 46 | from lp.buildmaster.interfaces.builder import CannotBuild |
319 | @@ -431,6 +431,20 @@ class TestAsyncSnapBuildBehaviourFetchService( | |||
320 | 431 | snap = self.factory.makeSnap(use_fetch_service=True) | 431 | snap = self.factory.makeSnap(use_fetch_service=True) |
321 | 432 | request = self.factory.makeSnapBuildRequest(snap=snap) | 432 | request = self.factory.makeSnapBuildRequest(snap=snap) |
322 | 433 | job = self.makeJob(snap=snap, build_request=request) | 433 | job = self.makeJob(snap=snap, build_request=request) |
323 | 434 | |||
324 | 435 | host = config.builddmaster.fetch_service_host | ||
325 | 436 | port = config.builddmaster.fetch_service_port | ||
326 | 437 | session_id = self.fetch_service_api.sessions.session_id | ||
327 | 438 | revocation_endpoint = ( | ||
328 | 439 | f"http://{host}:{port}/session/{session_id}/token" | ||
329 | 440 | ) | ||
330 | 441 | |||
331 | 442 | job._worker.proxy_info = MagicMock( | ||
332 | 443 | return_value={ | ||
333 | 444 | "revocation_endpoint": revocation_endpoint, | ||
334 | 445 | "use_fetch_service": True, | ||
335 | 446 | } | ||
336 | 447 | ) | ||
337 | 434 | yield job.extraBuildArgs() | 448 | yield job.extraBuildArgs() |
338 | 435 | 449 | ||
339 | 436 | # End the session | 450 | # End the session |
340 | @@ -443,7 +457,6 @@ class TestAsyncSnapBuildBehaviourFetchService( | |||
341 | 443 | start_session_request = self.fetch_service_api.sessions.requests[0] | 457 | start_session_request = self.fetch_service_api.sessions.requests[0] |
342 | 444 | self.assertEqual(b"POST", start_session_request["method"]) | 458 | self.assertEqual(b"POST", start_session_request["method"]) |
343 | 445 | self.assertEqual(b"/session", start_session_request["uri"]) | 459 | self.assertEqual(b"/session", start_session_request["uri"]) |
344 | 446 | session_id = self.fetch_service_api.sessions.responses[0]["id"] | ||
345 | 447 | 460 | ||
346 | 448 | # Request retrieve metadata | 461 | # Request retrieve metadata |
347 | 449 | retrieve_metadata_request = self.fetch_service_api.sessions.requests[1] | 462 | retrieve_metadata_request = self.fetch_service_api.sessions.requests[1] |
348 | @@ -478,6 +491,14 @@ class TestAsyncSnapBuildBehaviourFetchService( | |||
349 | 478 | snap = self.factory.makeSnap(use_fetch_service=False) | 491 | snap = self.factory.makeSnap(use_fetch_service=False) |
350 | 479 | request = self.factory.makeSnapBuildRequest(snap=snap) | 492 | request = self.factory.makeSnapBuildRequest(snap=snap) |
351 | 480 | job = self.makeJob(snap=snap, build_request=request) | 493 | job = self.makeJob(snap=snap, build_request=request) |
352 | 494 | |||
353 | 495 | job._worker.proxy_info = MagicMock( | ||
354 | 496 | return_value={ | ||
355 | 497 | "revocation_endpoint": "https://builder-proxy.test/revoke", | ||
356 | 498 | "use_fetch_service": False, | ||
357 | 499 | } | ||
358 | 500 | ) | ||
359 | 501 | |||
360 | 481 | yield job.extraBuildArgs() | 502 | yield job.extraBuildArgs() |
361 | 482 | yield job.endProxySession(upload_path="test_path") | 503 | yield job.endProxySession(upload_path="test_path") |
362 | 483 | 504 | ||
363 | @@ -485,23 +506,33 @@ class TestAsyncSnapBuildBehaviourFetchService( | |||
364 | 485 | self.assertEqual(0, len(self.fetch_service_api.sessions.requests)) | 506 | self.assertEqual(0, len(self.fetch_service_api.sessions.requests)) |
365 | 486 | 507 | ||
366 | 487 | @defer.inlineCallbacks | 508 | @defer.inlineCallbacks |
370 | 488 | def test_endProxySession_no_proxy_service(self): | 509 | def test_endProxySession_fetch_Service_allow_internet_false(self): |
371 | 489 | """When the `fetch_service_host` is not set, the calls to the fetch | 510 | """When `allow_internet` is False, we don't send proxy variables to the |
372 | 490 | service don't go through.""" | 511 | buildd, and ending the session does not make calls to the fetch |
373 | 512 | service.""" | ||
374 | 491 | self.useFixture( | 513 | self.useFixture( |
375 | 492 | FeatureFixture({SNAP_USE_FETCH_SERVICE_FEATURE_FLAG: "on"}) | 514 | FeatureFixture({SNAP_USE_FETCH_SERVICE_FEATURE_FLAG: "on"}) |
376 | 493 | ) | 515 | ) |
380 | 494 | self.useFixture(FeatureFixture({"fetch_service_host": None})) | 516 | snap = self.factory.makeSnap(allow_internet=False) |
378 | 495 | |||
379 | 496 | snap = self.factory.makeSnap(use_fetch_service=True) | ||
381 | 497 | request = self.factory.makeSnapBuildRequest(snap=snap) | 517 | request = self.factory.makeSnapBuildRequest(snap=snap) |
382 | 498 | job = self.makeJob(snap=snap, build_request=request) | 518 | job = self.makeJob(snap=snap, build_request=request) |
384 | 499 | yield job.extraBuildArgs() | 519 | args = yield job.extraBuildArgs() |
385 | 520 | |||
386 | 521 | # Scenario when we don't allow internet | ||
387 | 522 | job._worker.proxy_info = MagicMock( | ||
388 | 523 | return_value={ | ||
389 | 524 | "revocation_endpoint": None, | ||
390 | 525 | "use_fetch_service": None, | ||
391 | 526 | } | ||
392 | 527 | ) | ||
393 | 528 | |||
394 | 500 | yield job.endProxySession(upload_path="test_path") | 529 | yield job.endProxySession(upload_path="test_path") |
395 | 501 | 530 | ||
396 | 531 | # No proxy config sent to buildd | ||
397 | 532 | self.assertIsNone(args.get("use_fetch_service")) | ||
398 | 533 | self.assertIsNone(args.get("revocation_endpoint")) | ||
399 | 502 | # No calls go through to the fetch service | 534 | # No calls go through to the fetch service |
400 | 503 | self.assertEqual(0, len(self.fetch_service_api.sessions.requests)) | 535 | self.assertEqual(0, len(self.fetch_service_api.sessions.requests)) |
401 | 504 | self.assertEqual(None, job._proxy_service) | ||
402 | 505 | 536 | ||
403 | 506 | 537 | ||
404 | 507 | class TestAsyncSnapBuildBehaviourBuilderProxy( | 538 | class TestAsyncSnapBuildBehaviourBuilderProxy( |
405 | @@ -1470,8 +1501,6 @@ class TestAsyncSnapBuildBehaviourBuilderProxy( | |||
406 | 1470 | 1501 | ||
407 | 1471 | # End the session | 1502 | # End the session |
408 | 1472 | yield job.endProxySession(upload_path="test_path") | 1503 | yield job.endProxySession(upload_path="test_path") |
409 | 1473 | self.assertFalse(job.use_fetch_service) | ||
410 | 1474 | self.assertTrue(isinstance(job.proxy_service, BuilderProxy)) | ||
411 | 1475 | 1504 | ||
412 | 1476 | @defer.inlineCallbacks | 1505 | @defer.inlineCallbacks |
413 | 1477 | def test_composeBuildRequest_proxy_url_set(self): | 1506 | def test_composeBuildRequest_proxy_url_set(self): |
This has not been cleaned up (and mypy issues not fixed). Opening it up for an early review.