blob: 5f601cd79c63dbba7dcd584683de4a77347ac20e [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Evan Hernandezf388cbf2019-04-01 11:15:23 -06002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Implements ArtifactService."""
6
Chris McDonald1672ddb2021-07-21 11:48:23 -06007import logging
Evan Hernandezf388cbf2019-04-01 11:15:23 -06008import os
Varun Somani04dccd72021-10-09 01:06:11 +00009from typing import Any, NamedTuple, Optional, TYPE_CHECKING
Evan Hernandezf388cbf2019-04-01 11:15:23 -060010
Alex Klein231d2da2019-07-22 16:44:45 -060011from chromite.api import controller
Alex Klein076841b2019-08-29 15:19:39 -060012from chromite.api import faux
Alex Klein2b236722019-06-19 15:44:26 -060013from chromite.api import validate
Alex Klein238d8862019-05-07 11:32:46 -060014from chromite.api.controller import controller_util
George Engelbrechtc9a8e812021-06-16 18:14:17 -060015from chromite.api.controller import image as image_controller
16from chromite.api.controller import sysroot as sysroot_controller
David Wellingc1433c22021-06-25 16:29:48 +000017from chromite.api.controller import test as test_controller
LaMont Jones58362a42021-02-04 17:40:08 -070018from chromite.api.gen.chromite.api import artifacts_pb2
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000019from chromite.api.gen.chromiumos import common_pb2
Evan Hernandezf388cbf2019-04-01 11:15:23 -060020from chromite.lib import constants
21from chromite.lib import cros_build_lib
Alex Klein2275d692019-04-23 16:04:12 -060022from chromite.lib import sysroot_lib
23from chromite.service import artifacts
Greg Edelstondc941072021-08-11 12:32:30 -060024from chromite.service import test
Evan Hernandezf388cbf2019-04-01 11:15:23 -060025
Mike Frysinger1cc8f1f2022-04-28 22:40:40 -040026
Varun Somani04dccd72021-10-09 01:06:11 +000027if TYPE_CHECKING:
Alex Klein1699fab2022-09-08 08:46:06 -060028 from chromite.api import api_config
29
Evan Hernandezf388cbf2019-04-01 11:15:23 -060030
George Engelbrechtc9a8e812021-06-16 18:14:17 -060031class RegisteredGet(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -060032 """An registered function for calling Get on an artifact type."""
33
34 output_proto: artifacts_pb2.GetResponse
35 artifact_dict: Any
LaMont Jones0f5171b2021-01-29 12:28:56 -070036
37
George Engelbrechtc9a8e812021-06-16 18:14:17 -060038def ExampleGetResponse(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -060039 """Give an example GetResponse with a minimal coverage set."""
40 _output_proto = artifacts_pb2.GetResponse(
41 artifacts=common_pb2.UploadedArtifactsByService(
42 image=image_controller.ExampleGetResponse(),
43 sysroot=sysroot_controller.ExampleGetResponse(),
44 )
45 )
46 return controller.RETURN_CODE_SUCCESS
George Engelbrechtc9a8e812021-06-16 18:14:17 -060047
48
LaMont Jones0f5171b2021-01-29 12:28:56 -070049@faux.empty_error
George Engelbrechtc9a8e812021-06-16 18:14:17 -060050@faux.success(ExampleGetResponse)
Alex Klein1699fab2022-09-08 08:46:06 -060051@validate.exists("result_path.path.path")
LaMont Jones0f5171b2021-01-29 12:28:56 -070052@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +000053def Get(
54 input_proto: artifacts_pb2.GetRequest,
55 output_proto: artifacts_pb2.GetResponse,
Alex Klein1699fab2022-09-08 08:46:06 -060056 _config: "api_config.ApiConfig",
57):
58 """Get all artifacts.
LaMont Jones0f5171b2021-01-29 12:28:56 -070059
Alex Klein1699fab2022-09-08 08:46:06 -060060 Get all artifacts for the build.
LaMont Jones0f5171b2021-01-29 12:28:56 -070061
Alex Klein1699fab2022-09-08 08:46:06 -060062 Note: As the individual artifact_type bundlers are added here, they *must*
63 stop uploading it via the individual bundler function.
LaMont Jones0f5171b2021-01-29 12:28:56 -070064
Alex Klein1699fab2022-09-08 08:46:06 -060065 Args:
Alex Klein611dddd2022-10-11 17:02:01 -060066 input_proto: The input proto.
67 output_proto: The output proto.
68 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -060069 """
70 output_dir = input_proto.result_path.path.path
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000071
Alex Klein1699fab2022-09-08 08:46:06 -060072 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
73 # This endpoint does not currently support any artifacts that are built
74 # without a sysroot being present.
75 if not sysroot.path:
76 return controller.RETURN_CODE_SUCCESS
77
78 chroot = controller_util.ParseChroot(input_proto.chroot)
79 build_target = controller_util.ParseBuildTarget(
80 input_proto.sysroot.build_target
81 )
82
83 # A list of RegisteredGet tuples (input proto, output proto, get results).
84 get_res_list = [
85 RegisteredGet(
86 output_proto.artifacts.image,
87 image_controller.GetArtifacts(
88 input_proto.artifact_info.image,
89 chroot,
90 sysroot,
91 build_target,
92 output_dir,
93 ),
94 ),
95 RegisteredGet(
96 output_proto.artifacts.sysroot,
97 sysroot_controller.GetArtifacts(
98 input_proto.artifact_info.sysroot,
99 chroot,
100 sysroot,
101 build_target,
102 output_dir,
103 ),
104 ),
105 RegisteredGet(
106 output_proto.artifacts.test,
107 test_controller.GetArtifacts(
108 input_proto.artifact_info.test,
109 chroot,
110 sysroot,
111 build_target,
112 output_dir,
113 ),
114 ),
115 ]
116
117 for get_res in get_res_list:
118 for artifact_dict in get_res.artifact_dict:
Jack Neus26b94672022-10-27 17:33:21 +0000119 kwargs = {}
120 # TODO(b/255838545): Remove the kwargs funkness when these fields
121 # have been added for all services.
122 if "failed" in artifact_dict:
123 kwargs["failed"] = artifact_dict.get("failed", False)
124 kwargs["failure_reason"] = artifact_dict.get("failure_reason")
Alex Klein1699fab2022-09-08 08:46:06 -0600125 get_res.output_proto.artifacts.add(
126 artifact_type=artifact_dict["type"],
127 paths=[
128 common_pb2.Path(
129 path=x, location=common_pb2.Path.Location.OUTSIDE
130 )
Jack Neus26b94672022-10-27 17:33:21 +0000131 for x in artifact_dict.get("paths", [])
Alex Klein1699fab2022-09-08 08:46:06 -0600132 ],
Jack Neus26b94672022-10-27 17:33:21 +0000133 **kwargs,
Alex Klein1699fab2022-09-08 08:46:06 -0600134 )
LaMont Jones8b88e9d2021-06-28 16:37:34 -0600135 return controller.RETURN_CODE_SUCCESS
136
LaMont Jones0f5171b2021-01-29 12:28:56 -0700137
LaMont Jones58362a42021-02-04 17:40:08 -0700138def _BuildSetupResponse(_input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600139 """Just return POINTLESS for now."""
140 # All of the artifact types we support claim that the build is POINTLESS.
141 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
LaMont Jones58362a42021-02-04 17:40:08 -0700142
143
144@faux.success(_BuildSetupResponse)
145@faux.empty_error
146@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000147def BuildSetup(
148 _input_proto: artifacts_pb2.GetRequest,
149 output_proto: artifacts_pb2.GetResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600150 _config: "api_config.ApiConfig",
151):
Varun Somani04dccd72021-10-09 01:06:11 +0000152
Alex Klein1699fab2022-09-08 08:46:06 -0600153 """Setup anything needed for building artifacts
LaMont Jones58362a42021-02-04 17:40:08 -0700154
Alex Klein1699fab2022-09-08 08:46:06 -0600155 If any artifact types require steps prior to building the package, they go
156 here. For example, see ToolchainService/PrepareForBuild.
LaMont Jones58362a42021-02-04 17:40:08 -0700157
Alex Klein1699fab2022-09-08 08:46:06 -0600158 Note: crbug/1034529 introduces this method as a noop. As the individual
159 artifact_type bundlers are added here, they *must* stop uploading it via the
160 individual bundler function.
LaMont Jones58362a42021-02-04 17:40:08 -0700161
Alex Klein1699fab2022-09-08 08:46:06 -0600162 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600163 _input_proto: The input proto.
164 output_proto: The output proto.
165 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600166 """
167 # If any artifact_type says "NEEDED", the return is NEEDED.
168 # Otherwise, if any artifact_type says "UNKNOWN", the return is UNKNOWN.
169 # Otherwise, the return is POINTLESS.
170 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
171 return controller.RETURN_CODE_SUCCESS
LaMont Jones58362a42021-02-04 17:40:08 -0700172
173
Varun Somani04dccd72021-10-09 01:06:11 +0000174def _GetImageDir(build_root: str, target: str) -> Optional[str]:
Alex Klein1699fab2022-09-08 08:46:06 -0600175 """Return path containing images for the given build target.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600176
Alex Klein1699fab2022-09-08 08:46:06 -0600177 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
Alex Kleine2612a02019-04-18 13:51:06 -0600178
Alex Klein1699fab2022-09-08 08:46:06 -0600179 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600180 build_root: Path to checkout where build occurs.
181 target: Name of the build target.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600182
Alex Klein1699fab2022-09-08 08:46:06 -0600183 Returns:
Alex Klein611dddd2022-10-11 17:02:01 -0600184 Path to the latest directory containing target images or None.
Alex Klein1699fab2022-09-08 08:46:06 -0600185 """
186 image_dir = os.path.join(build_root, "src/build/images", target, "latest")
187 if not os.path.exists(image_dir):
188 logging.warning(
189 "Expected to find image output for target %s at %s, but "
190 "path does not exist",
191 target,
192 image_dir,
193 )
194 return None
Alex Kleind2bf1462019-10-24 16:37:04 -0600195
Alex Klein1699fab2022-09-08 08:46:06 -0600196 return image_dir
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600197
198
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700199def _BundleImageArchivesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600200 """Add artifact paths to a successful response."""
201 output_proto.artifacts.add().path = os.path.join(
202 input_proto.output_dir, "path0.tar.xz"
203 )
204 output_proto.artifacts.add().path = os.path.join(
205 input_proto.output_dir, "path1.tar.xz"
206 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700207
208
209@faux.success(_BundleImageArchivesResponse)
210@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600211@validate.require("build_target.name")
212@validate.exists("output_dir")
Alex Kleind91e95a2019-09-17 10:39:02 -0600213@validate.validation_complete
214def BundleImageArchives(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600215 """Create a .tar.xz archive for each image that has been created."""
216 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
217 output_dir = input_proto.output_dir
218 image_dir = _GetImageDir(constants.SOURCE_ROOT, build_target.name)
219 if image_dir is None:
220 return
Alex Kleind91e95a2019-09-17 10:39:02 -0600221
Alex Klein1699fab2022-09-08 08:46:06 -0600222 archives = artifacts.ArchiveImages(image_dir, output_dir)
Alex Kleind91e95a2019-09-17 10:39:02 -0600223
Alex Klein1699fab2022-09-08 08:46:06 -0600224 for archive in archives:
225 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Kleind91e95a2019-09-17 10:39:02 -0600226
227
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700228def _BundleImageZipResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600229 """Add artifact zip files to a successful response."""
230 output_proto.artifacts.add().path = os.path.join(
231 input_proto.output_dir, "image.zip"
232 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700233
234
235@faux.success(_BundleImageZipResponse)
236@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600237@validate.require("build_target.name", "output_dir")
238@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600239@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000240def BundleImageZip(
241 input_proto: artifacts_pb2.BundleRequest,
242 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600243 _config: "api_config.ApiConfig",
244):
245 """Bundle image.zip.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600246
Alex Klein1699fab2022-09-08 08:46:06 -0600247 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600248 input_proto: The input proto.
249 output_proto: The output proto.
250 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600251 """
252 target = input_proto.build_target.name
253 output_dir = input_proto.output_dir
254 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
255 if image_dir is None:
256 return None
Alex Klein231d2da2019-07-22 16:44:45 -0600257
Alex Klein1699fab2022-09-08 08:46:06 -0600258 archive = artifacts.BundleImageZip(output_dir, image_dir)
259 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600260
261
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700262def _BundleTestUpdatePayloadsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600263 """Add test payload files to a successful response."""
264 output_proto.artifacts.add().path = os.path.join(
265 input_proto.output_dir, "payload1.bin"
266 )
267 output_proto.artifacts.add().path = os.path.join(
268 input_proto.output_dir, "payload1.json"
269 )
270 output_proto.artifacts.add().path = os.path.join(
271 input_proto.output_dir, "payload1.log"
272 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700273
274
275@faux.success(_BundleTestUpdatePayloadsResponse)
276@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600277@validate.require("build_target.name", "output_dir")
278@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600279@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000280def BundleTestUpdatePayloads(
281 input_proto: artifacts_pb2.BundleRequest,
282 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600283 _config: "api_config.ApiConfig",
284):
285 """Generate minimal update payloads for the build target for testing.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600286
Alex Klein1699fab2022-09-08 08:46:06 -0600287 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600288 input_proto: The input proto.
289 output_proto: The output proto.
290 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600291 """
292 target = input_proto.build_target.name
293 output_dir = input_proto.output_dir
294 build_root = constants.SOURCE_ROOT
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600295
Alex Klein1699fab2022-09-08 08:46:06 -0600296 # Use the first available image to create the update payload.
297 img_dir = _GetImageDir(build_root, target)
298 if img_dir is None:
299 return None
Alex Kleind2bf1462019-10-24 16:37:04 -0600300
Alex Klein1699fab2022-09-08 08:46:06 -0600301 img_types = [
302 constants.IMAGE_TYPE_TEST,
303 constants.IMAGE_TYPE_DEV,
304 constants.IMAGE_TYPE_BASE,
305 ]
306 img_names = [constants.IMAGE_TYPE_TO_NAME[t] for t in img_types]
307 img_paths = [os.path.join(img_dir, x) for x in img_names]
308 valid_images = [x for x in img_paths if os.path.exists(x)]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600309
Alex Klein1699fab2022-09-08 08:46:06 -0600310 if not valid_images:
311 cros_build_lib.Die(
312 'Expected to find an image of type among %r for target "%s" '
313 "at path %s.",
314 img_types,
315 target,
316 img_dir,
317 )
318 image = valid_images[0]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600319
Alex Klein1699fab2022-09-08 08:46:06 -0600320 payloads = artifacts.BundleTestUpdatePayloads(image, output_dir)
321 for payload in payloads:
322 output_proto.artifacts.add().path = payload
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600323
324
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700325def _BundleAutotestFilesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600326 """Add test autotest files to a successful response."""
327 output_proto.artifacts.add().path = os.path.join(
328 input_proto.output_dir, "autotest-a.tar.gz"
329 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700330
331
332@faux.success(_BundleAutotestFilesResponse)
333@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600334@validate.require("sysroot.path")
335@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600336@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600337def BundleAutotestFiles(
338 input_proto: artifacts_pb2.BundleRequest,
339 output_proto: artifacts_pb2.BundleResponse,
340 _config: "api_config.ApiConfig",
341) -> None:
342 """Tar the autotest files for a build target."""
343 output_dir = input_proto.output_dir
344 chroot = controller_util.ParseChroot(input_proto.chroot)
345 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600346
Alex Klein1699fab2022-09-08 08:46:06 -0600347 if not sysroot.Exists(chroot=chroot):
348 logging.warning("Sysroot does not exist: %s", sysroot.path)
349 return
Alex Klein238d8862019-05-07 11:32:46 -0600350
Alex Klein1699fab2022-09-08 08:46:06 -0600351 try:
352 # Note that this returns the full path to *multiple* tarballs.
353 archives = artifacts.BundleAutotestFiles(chroot, sysroot, output_dir)
354 except artifacts.Error as e:
355 logging.warning(e)
356 return
Alex Klein238d8862019-05-07 11:32:46 -0600357
Alex Klein1699fab2022-09-08 08:46:06 -0600358 for archive in archives.values():
359 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600360
361
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700362def _BundleTastFilesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600363 """Add test tast files to a successful response."""
364 output_proto.artifacts.add().path = os.path.join(
365 input_proto.output_dir, "tast_bundles.tar.gz"
366 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700367
368
369@faux.success(_BundleTastFilesResponse)
370@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600371@validate.require("sysroot.path")
372@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600373@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600374def BundleTastFiles(
375 input_proto: artifacts_pb2.BundleRequest,
376 output_proto: artifacts_pb2.BundleResponse,
377 _config: "api_config.ApiConfig",
378) -> None:
379 """Tar the tast files for a build target."""
380 output_dir = input_proto.output_dir
381 chroot = controller_util.ParseChroot(input_proto.chroot)
382 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600383
Alex Klein1699fab2022-09-08 08:46:06 -0600384 if not sysroot.Exists(chroot=chroot):
385 logging.warning("Sysroot does not exist: %s", sysroot.path)
386 return
Alex Kleinb9d810b2019-07-01 12:38:02 -0600387
Alex Klein1699fab2022-09-08 08:46:06 -0600388 archive = artifacts.BundleTastFiles(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600389
Alex Klein1699fab2022-09-08 08:46:06 -0600390 if not archive:
391 logging.warning("Found no tast files for %s.", sysroot.path)
392 return
Alex Klein036833d2022-06-01 13:05:01 -0600393
Alex Klein1699fab2022-09-08 08:46:06 -0600394 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600395
396
Fergus Dall34d74e12020-09-29 15:52:32 +1000397def BundlePinnedGuestImages(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600398 # TODO(crbug/1034529): Remove this endpoint
399 pass
400
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700401
Fergus Dall34d74e12020-09-29 15:52:32 +1000402def FetchPinnedGuestImageUris(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600403 # TODO(crbug/1034529): Remove this endpoint
404 pass
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600405
406
Greg Edelstondc941072021-08-11 12:32:30 -0600407def _FetchMetadataResponse(_input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600408 """Populate the output_proto with sample data."""
409 for fp in ("/metadata/foo.txt", "/metadata/bar.jsonproto"):
410 output_proto.filepaths.add(
411 path=common_pb2.Path(path=fp, location=common_pb2.Path.OUTSIDE)
412 )
413 return controller.RETURN_CODE_SUCCESS
Greg Edelstondc941072021-08-11 12:32:30 -0600414
415
416@faux.success(_FetchMetadataResponse)
417@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600418@validate.exists("chroot.path")
419@validate.require("sysroot.path")
Greg Edelstondc941072021-08-11 12:32:30 -0600420@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000421def FetchMetadata(
422 input_proto: artifacts_pb2.FetchMetadataRequest,
423 output_proto: artifacts_pb2.FetchMetadataResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600424 _config: "api_config.ApiConfig",
425):
426 """FetchMetadata returns the paths to all build/test metadata files.
Greg Edelstondc941072021-08-11 12:32:30 -0600427
Alex Klein1699fab2022-09-08 08:46:06 -0600428 This implements ArtifactsService.FetchMetadata.
Greg Edelstondc941072021-08-11 12:32:30 -0600429
Alex Klein1699fab2022-09-08 08:46:06 -0600430 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600431 input_proto: The input proto.
432 output_proto: The output proto.
433 config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600434 """
435 chroot = controller_util.ParseChroot(input_proto.chroot)
436 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
437 for path in test.FindAllMetadataFiles(chroot, sysroot):
438 output_proto.filepaths.add(
439 path=common_pb2.Path(path=path, location=common_pb2.Path.OUTSIDE)
440 )
441 return controller.RETURN_CODE_SUCCESS
Greg Edelstondc941072021-08-11 12:32:30 -0600442
443
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700444def _BundleFirmwareResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600445 """Add test firmware image files to a successful response."""
446 output_proto.artifacts.add().path = os.path.join(
447 input_proto.output_dir, "firmware.tar.gz"
448 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700449
450
451@faux.success(_BundleFirmwareResponse)
452@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600453@validate.require("sysroot.path")
454@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600455@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600456def BundleFirmware(
457 input_proto: artifacts_pb2.BundleRequest,
458 output_proto: artifacts_pb2.BundleResponse,
459 _config: "api_config.ApiConfig",
460) -> None:
461 """Tar the firmware images for a build target."""
462 output_dir = input_proto.output_dir
463 chroot = controller_util.ParseChroot(input_proto.chroot)
464 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600465
Alex Klein1699fab2022-09-08 08:46:06 -0600466 if not chroot.exists():
467 logging.warning("Chroot does not exist: %s", chroot.path)
468 return
469 elif not sysroot.Exists(chroot=chroot):
470 logging.warning("Sysroot does not exist: %s", sysroot.path)
471 return
Alex Klein231d2da2019-07-22 16:44:45 -0600472
Alex Klein1699fab2022-09-08 08:46:06 -0600473 archive = artifacts.BuildFirmwareArchive(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600474
Alex Klein1699fab2022-09-08 08:46:06 -0600475 if not archive:
476 logging.warning(
477 "Could not create firmware archive. No firmware found for %s.",
478 sysroot.path,
479 )
480 return
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600481
Alex Klein1699fab2022-09-08 08:46:06 -0600482 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600483
484
Yicheng Liea1181f2020-09-22 11:51:10 -0700485def _BundleFpmcuUnittestsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600486 """Add fingerprint MCU unittest binaries to a successful response."""
487 output_proto.artifacts.add().path = os.path.join(
488 input_proto.output_dir, "fpmcu_unittests.tar.gz"
489 )
Yicheng Liea1181f2020-09-22 11:51:10 -0700490
491
492@faux.success(_BundleFpmcuUnittestsResponse)
493@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600494@validate.require("sysroot.path")
495@validate.exists("output_dir")
Yicheng Liea1181f2020-09-22 11:51:10 -0700496@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600497def BundleFpmcuUnittests(
498 input_proto: artifacts_pb2.BundleRequest,
499 output_proto: artifacts_pb2.BundleResponse,
500 _config: "api_config.ApiConfig",
501) -> None:
502 """Tar the fingerprint MCU unittest binaries for a build target.
Yicheng Liea1181f2020-09-22 11:51:10 -0700503
Alex Klein1699fab2022-09-08 08:46:06 -0600504 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600505 input_proto: The input proto.
506 output_proto: The output proto.
507 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600508 """
509 output_dir = input_proto.output_dir
510 chroot = controller_util.ParseChroot(input_proto.chroot)
511 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Yicheng Liea1181f2020-09-22 11:51:10 -0700512
Alex Klein1699fab2022-09-08 08:46:06 -0600513 if not chroot.exists():
514 logging.warning("Chroot does not exist: %s", chroot.path)
515 return
516 elif not sysroot.Exists(chroot=chroot):
517 logging.warning("Sysroot does not exist: %s", sysroot.path)
518 return
Yicheng Liea1181f2020-09-22 11:51:10 -0700519
Alex Klein1699fab2022-09-08 08:46:06 -0600520 archive = artifacts.BundleFpmcuUnittests(chroot, sysroot, output_dir)
Yicheng Liea1181f2020-09-22 11:51:10 -0700521
Alex Klein1699fab2022-09-08 08:46:06 -0600522 if not archive:
523 logging.warning("No fpmcu unittests found for %s.", sysroot.path)
524 return
Yicheng Liea1181f2020-09-22 11:51:10 -0700525
Alex Klein1699fab2022-09-08 08:46:06 -0600526 output_proto.artifacts.add().path = archive
Yicheng Liea1181f2020-09-22 11:51:10 -0700527
528
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700529def _BundleEbuildLogsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600530 """Add test log files to a successful response."""
531 output_proto.artifacts.add().path = os.path.join(
532 input_proto.output_dir, "ebuild-logs.tar.gz"
533 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700534
535
536@faux.success(_BundleEbuildLogsResponse)
537@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600538@validate.require("sysroot.path")
539@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600540@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600541def BundleEbuildLogs(
542 input_proto: artifacts_pb2.BundleRequest,
543 output_proto: artifacts_pb2.BundleResponse,
544 _config: "api_config.ApiConfig",
545) -> None:
546 """Tar the ebuild logs for a build target."""
547 output_dir = input_proto.output_dir
548 chroot = controller_util.ParseChroot(input_proto.chroot)
549 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Evan Hernandeza478d802019-04-08 15:08:24 -0600550
Alex Klein1699fab2022-09-08 08:46:06 -0600551 if not sysroot.Exists(chroot=chroot):
552 logging.warning("Sysroot does not exist: %s", sysroot.path)
553 return
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600554
Alex Klein1699fab2022-09-08 08:46:06 -0600555 archive = artifacts.BundleEBuildLogsTarball(chroot, sysroot, output_dir)
Alex Klein036833d2022-06-01 13:05:01 -0600556
Alex Klein1699fab2022-09-08 08:46:06 -0600557 if not archive:
558 logging.warning(
559 "Could not create ebuild logs archive. No logs found for %s.",
560 sysroot.path,
561 )
562 return
Alex Klein036833d2022-06-01 13:05:01 -0600563
Alex Klein1699fab2022-09-08 08:46:06 -0600564 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600565
566
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700567def _BundleChromeOSConfigResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600568 """Add test config files to a successful response."""
569 output_proto.artifacts.add().path = os.path.join(
570 input_proto.output_dir, "config.yaml"
571 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700572
573
574@faux.success(_BundleChromeOSConfigResponse)
575@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600576@validate.require("sysroot.path")
577@validate.exists("output_dir")
Andrew Lamb811aead2019-08-12 10:25:05 -0600578@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000579def BundleChromeOSConfig(
580 input_proto: artifacts_pb2.BundleRequest,
581 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600582 _config: "api_config.ApiConfig",
583) -> None:
584 """Output the ChromeOS Config payload for a build target."""
585 output_dir = input_proto.output_dir
586 chroot = controller_util.ParseChroot(input_proto.chroot)
587 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Andrew Lamb811aead2019-08-12 10:25:05 -0600588
Alex Klein1699fab2022-09-08 08:46:06 -0600589 chromeos_config = artifacts.BundleChromeOSConfig(
590 chroot, sysroot, output_dir
591 )
Alex Klein2d8333c2022-06-01 13:29:01 -0600592
Alex Klein1699fab2022-09-08 08:46:06 -0600593 if not chromeos_config:
594 logging.warning(
595 "Could not create ChromeOS Config for %s.", sysroot.path
596 )
597 return
Alex Klein383a7a32021-12-07 16:01:19 -0700598
Alex Klein1699fab2022-09-08 08:46:06 -0600599 output_proto.artifacts.add().path = os.path.join(
600 output_dir, chromeos_config
601 )
Andrew Lamb811aead2019-08-12 10:25:05 -0600602
603
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700604def _BundleSimpleChromeArtifactsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600605 """Add test simple chrome files to a successful response."""
606 output_proto.artifacts.add().path = os.path.join(
607 input_proto.output_dir, "simple_chrome.txt"
608 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700609
610
611@faux.success(_BundleSimpleChromeArtifactsResponse)
612@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600613@validate.require("output_dir", "sysroot.build_target.name", "sysroot.path")
614@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600615@validate.validation_complete
616def BundleSimpleChromeArtifacts(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600617 """Create the simple chrome artifacts."""
618 sysroot_path = input_proto.sysroot.path
619 output_dir = input_proto.output_dir
Alex Klein2275d692019-04-23 16:04:12 -0600620
Alex Klein1699fab2022-09-08 08:46:06 -0600621 # Build out the argument instances.
622 build_target = controller_util.ParseBuildTarget(
623 input_proto.sysroot.build_target
624 )
625 chroot = controller_util.ParseChroot(input_proto.chroot)
626 # Sysroot.path needs to be the fully qualified path, including the chroot.
627 full_sysroot_path = os.path.join(chroot.path, sysroot_path.lstrip(os.sep))
628 sysroot = sysroot_lib.Sysroot(full_sysroot_path)
Alex Klein2275d692019-04-23 16:04:12 -0600629
Alex Klein1699fab2022-09-08 08:46:06 -0600630 # Check that the sysroot exists before we go on.
631 if not sysroot.Exists():
632 cros_build_lib.Die("The sysroot does not exist.")
Alex Klein2275d692019-04-23 16:04:12 -0600633
Alex Klein1699fab2022-09-08 08:46:06 -0600634 try:
635 results = artifacts.BundleSimpleChromeArtifacts(
636 chroot, sysroot, build_target, output_dir
637 )
638 except artifacts.Error as e:
639 cros_build_lib.Die(
640 "Error %s raised in BundleSimpleChromeArtifacts: %s", type(e), e
641 )
Alex Klein2275d692019-04-23 16:04:12 -0600642
Alex Klein1699fab2022-09-08 08:46:06 -0600643 for file_name in results:
644 output_proto.artifacts.add().path = file_name
Alex Klein2275d692019-04-23 16:04:12 -0600645
646
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700647def _BundleVmFilesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600648 """Add test vm files to a successful response."""
649 output_proto.artifacts.add().path = os.path.join(
650 input_proto.output_dir, "f1.tar"
651 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700652
653
654@faux.success(_BundleVmFilesResponse)
655@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600656@validate.require("chroot.path", "test_results_dir", "output_dir")
657@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600658@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000659def BundleVmFiles(
660 input_proto: artifacts_pb2.BundleVmFilesRequest,
661 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600662 _config: "api_config.ApiConfig",
663):
664 """Tar VM disk and memory files.
Alex Klein6504eca2019-04-18 15:37:56 -0600665
Alex Klein1699fab2022-09-08 08:46:06 -0600666 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600667 input_proto: The input proto.
668 output_proto: The output proto.
669 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600670 """
671 chroot = controller_util.ParseChroot(input_proto.chroot)
672 test_results_dir = input_proto.test_results_dir
673 output_dir = input_proto.output_dir
Alex Klein6504eca2019-04-18 15:37:56 -0600674
Alex Klein1699fab2022-09-08 08:46:06 -0600675 archives = artifacts.BundleVmFiles(chroot, test_results_dir, output_dir)
676 for archive in archives:
677 output_proto.artifacts.add().path = archive
678
Tiancong Wangc4805b72019-06-11 12:12:03 -0700679
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700680def _ExportCpeReportResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600681 """Add test cpe results to a successful response."""
682 output_proto.artifacts.add().path = os.path.join(
683 input_proto.output_dir, "cpe_report.txt"
684 )
685 output_proto.artifacts.add().path = os.path.join(
686 input_proto.output_dir, "cpe_warnings.txt"
687 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700688
689
690@faux.success(_ExportCpeReportResponse)
691@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600692@validate.require("sysroot.path")
693@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600694@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600695def ExportCpeReport(
696 input_proto: artifacts_pb2.BundleRequest,
697 output_proto: artifacts_pb2.BundleResponse,
698 _config: "api_config.ApiConfig",
699) -> None:
700 """Export a CPE report."""
701 chroot = controller_util.ParseChroot(input_proto.chroot)
702 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
703 output_dir = input_proto.output_dir
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600704
Alex Klein1699fab2022-09-08 08:46:06 -0600705 if not sysroot.Exists(chroot=chroot):
706 logging.warning("Sysroot does not exist: %s", sysroot.path)
707 return
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600708
Alex Klein1699fab2022-09-08 08:46:06 -0600709 cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600710
Alex Klein1699fab2022-09-08 08:46:06 -0600711 output_proto.artifacts.add().path = cpe_result.report
712 output_proto.artifacts.add().path = cpe_result.warnings
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900713
714
715def _BundleGceTarballResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600716 """Add artifact tarball to a successful response."""
717 output_proto.artifacts.add().path = os.path.join(
718 input_proto.output_dir, constants.TEST_IMAGE_GCE_TAR
719 )
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900720
721
722@faux.success(_BundleGceTarballResponse)
723@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600724@validate.require("build_target.name", "output_dir")
725@validate.exists("output_dir")
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900726@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000727def BundleGceTarball(
728 input_proto: artifacts_pb2.BundleRequest,
729 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600730 _config: "api_config.ApiConfig",
731):
732 """Bundle the test image into a tarball suitable for importing into GCE.
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900733
Alex Klein1699fab2022-09-08 08:46:06 -0600734 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600735 input_proto: The input proto.
736 output_proto: The output proto.
737 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600738 """
739 target = input_proto.build_target.name
740 output_dir = input_proto.output_dir
741 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
742 if image_dir is None:
743 return None
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900744
Alex Klein1699fab2022-09-08 08:46:06 -0600745 tarball = artifacts.BundleGceTarball(output_dir, image_dir)
746 output_proto.artifacts.add().path = tarball