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/validate.py b/api/validate.py
index a42b5d3..ccdb2f9 100644
--- a/api/validate.py
+++ b/api/validate.py
@@ -65,13 +65,37 @@
   return decorator
 
 
+def is_in(field, values):
+  """Validate |field| does not contain |value|.
+
+  Args:
+    field (str): The field being checked. May be . separated nested fields.
+    values (list): The possible values field may take.
+  """
+  assert field
+  assert values
+
+  def decorator(func):
+    def _is_in(input_proto, *args, **kwargs):
+      logging.debug('Validating %s is in %r', field, values)
+      value = _value(field, input_proto)
+
+      if value not in values:
+        cros_build_lib.Die('%s (%r) must be in %r', field, value, values)
+
+      return func(input_proto, *args, **kwargs)
+
+    return _is_in
+
+  return decorator
+
+
 #pylint: disable=docstring-misnamed-args
 def require(*fields):
   """Verify |fields| have all been set.
 
   Args:
-    fields (str): The fields being checked. May be . separated nested
-      fields.
+    fields (str): The fields being checked. May be . separated nested fields.
   """
   assert fields