api: artifacts: Switch over to result_path and artifact_path

For everything still using Bundle{Request,Response}. This will make
the transition to running these APIs inside the chroot easier.

NB: this leaves out BundleVmFiles(), because it uses a unique request
type, and it has a simple implementation than handles outside-chroot
operation just fine.

BUG=b:187787264
TEST=./run_tests
TEST=api/compile_build_api_proto

Change-Id: I0315bd2e83663dfbb752c2a501bb29f4e1af0ed4
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/4698295
Commit-Queue: Brian Norris <briannorris@chromium.org>
Tested-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Alex Klein <saklein@chromium.org>
diff --git a/api/controller/artifacts.py b/api/controller/artifacts.py
index 14190c4..95d348c 100644
--- a/api/controller/artifacts.py
+++ b/api/controller/artifacts.py
@@ -187,18 +187,28 @@
 
 def _BundleImageArchivesResponse(input_proto, output_proto, _config) -> None:
     """Add artifact paths to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "path0.tar.xz"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "path0.tar.xz"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "path1.tar.xz"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "path1.tar.xz"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleImageArchivesResponse)
 @faux.empty_error
 @validate.require("sysroot.build_target.name", "sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleImageArchives(
     input_proto: artifacts_pb2.BundleRequest,
@@ -211,7 +221,7 @@
     )
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     image_dir = _GetImageDir(constants.SOURCE_ROOT, build_target.name)
     if image_dir is None:
         return
@@ -222,20 +232,28 @@
     archives = artifacts.ArchiveImages(chroot, sysroot, image_dir, output_dir)
 
     for archive in archives:
-        output_proto.artifacts.add().path = os.path.join(output_dir, archive)
+        output_proto.artifacts.add(
+            artifact_path=common_pb2.Path(
+                path=os.path.join(output_dir, archive),
+                location=common_pb2.Path.OUTSIDE,
+            )
+        )
 
 
 def _BundleImageZipResponse(input_proto, output_proto, _config) -> None:
     """Add artifact zip files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "image.zip"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(input_proto.result_path.path.path, "image.zip"),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleImageZipResponse)
 @faux.empty_error
-@validate.require("build_target.name", "output_dir")
-@validate.exists("output_dir")
+@validate.require("build_target.name", "result_path.path.path")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleImageZip(
     input_proto: artifacts_pb2.BundleRequest,
@@ -244,35 +262,55 @@
 ) -> Optional[int]:
     """Bundle image.zip."""
     target = input_proto.build_target.name
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
     if image_dir is None:
         logging.warning("Image build directory not found.")
         return None
 
     archive = artifacts.BundleImageZip(output_dir, image_dir)
-    output_proto.artifacts.add().path = os.path.join(output_dir, archive)
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(output_dir, archive),
+            location=common_pb2.Path.OUTSIDE,
+        )
+    )
 
 
 def _BundleTestUpdatePayloadsResponse(
     input_proto, output_proto, _config
 ) -> None:
     """Add test payload files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "payload1.bin"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "payload1.bin"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "payload1.json"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "payload1.json"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "payload1.log"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "payload1.log"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleTestUpdatePayloadsResponse)
 @faux.empty_error
-@validate.require("build_target.name", "output_dir")
-@validate.exists("output_dir")
+@validate.require("build_target.name", "result_path.path.path")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleTestUpdatePayloads(
     input_proto: artifacts_pb2.BundleRequest,
@@ -281,7 +319,7 @@
 ) -> Optional[int]:
     """Generate minimal update payloads for the build target for testing."""
     target = input_proto.build_target.name
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     chroot = controller_util.ParseChroot(input_proto.chroot)
     build_root = constants.SOURCE_ROOT
 
@@ -311,20 +349,29 @@
 
     payloads = artifacts.BundleTestUpdatePayloads(chroot, image, output_dir)
     for payload in payloads:
-        output_proto.artifacts.add().path = payload
+        output_proto.artifacts.add(
+            artifact_path=common_pb2.Path(
+                path=payload, location=common_pb2.Path.OUTSIDE
+            ),
+        )
 
 
 def _BundleAutotestFilesResponse(input_proto, output_proto, _config) -> None:
     """Add test autotest files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "autotest-a.tar.gz"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "autotest-a.tar.gz"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleAutotestFilesResponse)
 @faux.empty_error
 @validate.require("sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleAutotestFiles(
     input_proto: artifacts_pb2.BundleRequest,
@@ -332,7 +379,7 @@
     _config: "api_config.ApiConfig",
 ) -> Optional[int]:
     """Tar the autotest files for a build target."""
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
 
@@ -348,20 +395,29 @@
         return
 
     for archive in archives.values():
-        output_proto.artifacts.add().path = archive
+        output_proto.artifacts.add(
+            artifact_path=common_pb2.Path(
+                path=archive, location=common_pb2.Path.OUTSIDE
+            )
+        )
 
 
 def _BundleTastFilesResponse(input_proto, output_proto, _config) -> None:
     """Add test tast files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "tast_bundles.tar.gz"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "tast_bundles.tar.gz"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleTastFilesResponse)
 @faux.empty_error
 @validate.require("sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleTastFiles(
     input_proto: artifacts_pb2.BundleRequest,
@@ -369,7 +425,7 @@
     _config: "api_config.ApiConfig",
 ) -> Optional[int]:
     """Tar the tast files for a build target."""
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
 
@@ -383,7 +439,11 @@
         logging.warning("Found no tast files for %s.", sysroot.path)
         return
 
-    output_proto.artifacts.add().path = archive
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=archive, location=common_pb2.Path.OUTSIDE
+        )
+    )
 
 
 def BundlePinnedGuestImages(_input_proto, _output_proto, _config):
@@ -432,15 +492,20 @@
 
 def _BundleFirmwareResponse(input_proto, output_proto, _config):
     """Add test firmware image files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "firmware.tar.gz"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "firmware.tar.gz"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleFirmwareResponse)
 @faux.empty_error
 @validate.require("sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleFirmware(
     input_proto: artifacts_pb2.BundleRequest,
@@ -448,7 +513,7 @@
     _config: "api_config.ApiConfig",
 ) -> Optional[int]:
     """Tar the firmware images for a build target."""
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
 
@@ -468,20 +533,29 @@
         )
         return
 
-    output_proto.artifacts.add().path = archive
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=archive, location=common_pb2.Path.OUTSIDE
+        )
+    )
 
 
 def _BundleFpmcuUnittestsResponse(input_proto, output_proto, _config) -> None:
     """Add fingerprint MCU unittest binaries to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "fpmcu_unittests.tar.gz"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "fpmcu_unittests.tar.gz"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleFpmcuUnittestsResponse)
 @faux.empty_error
 @validate.require("sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleFpmcuUnittests(
     input_proto: artifacts_pb2.BundleRequest,
@@ -489,7 +563,7 @@
     _config: "api_config.ApiConfig",
 ) -> Optional[int]:
     """Tar the fingerprint MCU unittest binaries for a build target."""
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
 
@@ -506,20 +580,29 @@
         logging.warning("No fpmcu unittests found for %s.", sysroot.path)
         return
 
-    output_proto.artifacts.add().path = archive
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=archive, location=common_pb2.Path.OUTSIDE
+        )
+    )
 
 
 def _BundleEbuildLogsResponse(input_proto, output_proto, _config) -> None:
     """Add test log files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "ebuild-logs.tar.gz"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "ebuild-logs.tar.gz"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleEbuildLogsResponse)
 @faux.empty_error
 @validate.require("sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleEbuildLogs(
     input_proto: artifacts_pb2.BundleRequest,
@@ -527,7 +610,7 @@
     _config: "api_config.ApiConfig",
 ) -> Optional[int]:
     """Tar the ebuild logs for a build target."""
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
 
@@ -544,20 +627,28 @@
         )
         return
 
-    output_proto.artifacts.add().path = os.path.join(output_dir, archive)
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(output_dir, archive),
+            location=common_pb2.Path.OUTSIDE,
+        )
+    )
 
 
 def _BundleChromeOSConfigResponse(input_proto, output_proto, _config) -> None:
     """Add test config files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "config.yaml"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(input_proto.result_path.path.path, "config.yaml"),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleChromeOSConfigResponse)
 @faux.empty_error
 @validate.require("sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleChromeOSConfig(
     input_proto: artifacts_pb2.BundleRequest,
@@ -565,7 +656,7 @@
     _config: "api_config.ApiConfig",
 ) -> Optional[int]:
     """Output the ChromeOS Config payload for a build target."""
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
 
@@ -579,8 +670,11 @@
         )
         return
 
-    output_proto.artifacts.add().path = os.path.join(
-        output_dir, chromeos_config
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(output_dir, chromeos_config),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
@@ -588,22 +682,29 @@
     input_proto, output_proto, _config
 ) -> None:
     """Add test simple chrome files to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "simple_chrome.txt"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "simple_chrome.txt"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleSimpleChromeArtifactsResponse)
 @faux.empty_error
-@validate.require("output_dir", "sysroot.build_target.name", "sysroot.path")
-@validate.exists("output_dir")
+@validate.require(
+    "result_path.path.path", "sysroot.build_target.name", "sysroot.path"
+)
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleSimpleChromeArtifacts(
     input_proto, output_proto, _config
 ) -> Optional[int]:
     """Create the simple chrome artifacts."""
     sysroot_path = input_proto.sysroot.path
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
 
     # Build out the argument instances.
     build_target = controller_util.ParseBuildTarget(
@@ -630,7 +731,11 @@
         return
 
     for file_name in results:
-        output_proto.artifacts.add().path = file_name
+        output_proto.artifacts.add(
+            artifact_path=common_pb2.Path(
+                path=file_name, location=common_pb2.Path.OUTSIDE
+            )
+        )
 
 
 def _BundleVmFilesResponse(input_proto, output_proto, _config) -> None:
@@ -662,18 +767,28 @@
 
 def _ExportCpeReportResponse(input_proto, output_proto, _config):
     """Add test cpe results to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "cpe_report.txt"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "cpe_report.txt"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, "cpe_warnings.txt"
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, "cpe_warnings.txt"
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_ExportCpeReportResponse)
 @faux.empty_error
 @validate.require("sysroot.path")
-@validate.exists("output_dir")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def ExportCpeReport(
     input_proto: artifacts_pb2.BundleRequest,
@@ -683,7 +798,7 @@
     """Export a CPE report."""
     chroot = controller_util.ParseChroot(input_proto.chroot)
     sysroot = controller_util.ParseSysroot(input_proto.sysroot)
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
 
     if not sysroot.Exists(chroot=chroot):
         logging.warning("Sysroot does not exist: %s", sysroot.path)
@@ -691,21 +806,34 @@
 
     cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
 
-    output_proto.artifacts.add().path = cpe_result.report
-    output_proto.artifacts.add().path = cpe_result.warnings
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=cpe_result.report, location=common_pb2.Path.OUTSIDE
+        )
+    )
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=cpe_result.warnings, location=common_pb2.Path.OUTSIDE
+        )
+    )
 
 
 def _BundleGceTarballResponse(input_proto, output_proto, _config) -> None:
     """Add artifact tarball to a successful response."""
-    output_proto.artifacts.add().path = os.path.join(
-        input_proto.output_dir, constants.TEST_IMAGE_GCE_TAR
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=os.path.join(
+                input_proto.result_path.path.path, constants.TEST_IMAGE_GCE_TAR
+            ),
+            location=common_pb2.Path.OUTSIDE,
+        )
     )
 
 
 @faux.success(_BundleGceTarballResponse)
 @faux.empty_error
-@validate.require("build_target.name", "output_dir")
-@validate.exists("output_dir")
+@validate.require("build_target.name", "result_path.path.path")
+@validate.exists("result_path.path.path")
 @validate.validation_complete
 def BundleGceTarball(
     input_proto: artifacts_pb2.BundleRequest,
@@ -714,10 +842,14 @@
 ) -> Optional[int]:
     """Bundle the test image into a tarball suitable for importing into GCE."""
     target = input_proto.build_target.name
-    output_dir = input_proto.output_dir
+    output_dir = input_proto.result_path.path.path
     image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
     if image_dir is None:
         return None
 
     tarball = artifacts.BundleGceTarball(output_dir, image_dir)
-    output_proto.artifacts.add().path = tarball
+    output_proto.artifacts.add(
+        artifact_path=common_pb2.Path(
+            path=tarball, location=common_pb2.Path.OUTSIDE
+        )
+    )