api/controller: Add require_each validation.

The new require_each validator allows validation we were previously
unable to do automatically. Add usages in appropriate locations.

BUG=None
TEST=./run_pytest

Change-Id: I7efefc95ec1f1f500c41f31ab2797e33ce5eab01
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/2426960
Commit-Queue: Alex Klein <saklein@chromium.org>
Tested-by: Alex Klein <saklein@chromium.org>
Reviewed-by: Michael Mortensen <mmortensen@google.com>
diff --git a/api/controller/sysroot.py b/api/controller/sysroot.py
index a48c4c0..9c42614 100644
--- a/api/controller/sysroot.py
+++ b/api/controller/sysroot.py
@@ -77,6 +77,7 @@
 
 @faux.all_empty
 @validate.require('build_target.name', 'packages')
+@validate.require_each('packages', ['category', 'package_name'])
 @validate.validation_complete
 def GenerateArchive(input_proto, output_proto, _config):
   """Generate a sysroot. Typically used by informational builders."""
@@ -144,6 +145,8 @@
 @faux.error(_MockFailedPackagesResponse)
 @validate.require('sysroot.build_target.name')
 @validate.exists('sysroot.path')
+@validate.require_each('packages', ['category', 'package_name'])
+@validate.require_each('use_flags', ['flag'])
 @validate.validation_complete
 @metrics.collect_metrics
 def InstallPackages(input_proto, output_proto, _config):
@@ -161,9 +164,6 @@
   # error only when we cannot parse an atom for each of the given packages.
   packages = [controller_util.PackageInfoToCPV(x).cp
               for x in input_proto.packages]
-  if input_proto.packages and not all(packages):
-    cros_build_lib.Die(
-        'Invalid package(s) specified. Unable to parse atom from all packages.')
 
   package_indexes = [
       binpkg.PackageIndexInfo.from_protobuf(x)