Build API: Implement validate_only calls.

Add validate-only support to all existing endpoints and
tests to enforce the setting is respected.
Add is_in validator to help transition some endpoints
to decorator-only validation.
Some cleanup and standardization in the controller tests.

BUG=chromium:987263
TEST=run_tests

Cq-Depend: chromium:1726252
Change-Id: I108dfc1a221847eae47a18f2f60e12d2575c9ea8
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/1726253
Reviewed-by: David Burger <dburger@chromium.org>
Commit-Queue: Alex Klein <saklein@chromium.org>
Tested-by: Alex Klein <saklein@chromium.org>
diff --git a/api/controller/toolchain_unittest.py b/api/controller/toolchain_unittest.py
index 5175e89..1fa9525 100644
--- a/api/controller/toolchain_unittest.py
+++ b/api/controller/toolchain_unittest.py
@@ -10,6 +10,7 @@
 import mock
 import os
 
+from chromite.api import api_config
 from chromite.api.controller import toolchain
 from chromite.api.gen.chromite.api import toolchain_pb2
 
@@ -18,7 +19,8 @@
 from chromite.lib import toolchain_util
 
 
-class UpdateChromeEbuildWithOrderfileTest(cros_test_lib.MockTestCase):
+class UpdateChromeEbuildWithOrderfileTest(cros_test_lib.MockTestCase,
+                                          api_config.ApiConfigMixin):
   """Unittests for UpdateChromeEbuildWithOrderfile."""
 
   def setUp(self):
@@ -28,15 +30,25 @@
     self.input_proto = toolchain_pb2.UpdateChromeEbuildRequest(
         build_target={'name': self.board})
 
+  def testValidateOnly(self):
+    """Sanity check that a validate only call does not execute any logic."""
+    patch = self.PatchObject(toolchain_util, 'OrderfileUpdateChromeEbuild')
+
+    response = toolchain_pb2.UpdateChromeEbuildResponse()
+    toolchain.UpdateChromeEbuildWithOrderfile(self.input_proto, response,
+                                              self.validate_only_config)
+    patch.assert_not_called()
+
   def testSuccess(self):
     """Test the command is called correctly."""
     output_proto = toolchain_pb2.UpdateChromeEbuildResponse()
     toolchain.UpdateChromeEbuildWithOrderfile(self.input_proto,
-                                              output_proto)
+                                              output_proto, self.api_config)
     self.command.assert_called_once_with(self.board)
 
 
-class UploadVettedOrderfileTest(cros_test_lib.MockTestCase):
+class UploadVettedOrderfileTest(cros_test_lib.MockTestCase,
+                                api_config.ApiConfigMixin):
   """Unittests for UploadVettedOrderfile."""
 
   def setUp(self):
@@ -51,11 +63,21 @@
                                'orderfile-3.0.tar.xz')
     self.input_proto = toolchain_pb2.UploadVettedOrderfileRequest()
 
+  def testValidateOnly(self):
+    """Sanity check that a validate only call does not execute any logic."""
+    patch = self.PatchObject(toolchain_util, 'OrderfileUpdateChromeEbuild')
+
+    response = toolchain_pb2.UploadVettedOrderfileResponse()
+    toolchain.UploadVettedOrderfile(self.input_proto, response,
+                                    self.validate_only_config)
+    patch.assert_not_called()
+
   def testRunFail(self):
     """Test that it fails to upload an orderfile because it's already vetted."""
     exist_command = self.PatchObject(gs.GSContext, 'Exists', return_value=True)
     output_proto = toolchain_pb2.UploadVettedOrderfileResponse()
-    toolchain.UploadVettedOrderfile(self.input_proto, output_proto)
+    toolchain.UploadVettedOrderfile(self.input_proto, output_proto,
+                                    self.api_config)
     self.assertFalse(output_proto.status)
     self.find_command.assert_called_once_with(
         toolchain_util.ORDERFILE_GS_URL_UNVETTED)
@@ -65,7 +87,8 @@
     """Test run successfully."""
     exist_command = self.PatchObject(gs.GSContext, 'Exists', return_value=False)
     output_proto = toolchain_pb2.UploadVettedOrderfileResponse()
-    toolchain.UploadVettedOrderfile(self.input_proto, output_proto)
+    toolchain.UploadVettedOrderfile(self.input_proto, output_proto,
+                                    self.api_config)
     self.assertTrue(output_proto.status)
     self.find_command.assert_called_once_with(
         toolchain_util.ORDERFILE_GS_URL_UNVETTED)