Build API: Support binary serialization.
BUG=chromium:1032573
TEST=run_tests
TEST=manually ran endpoints
TEST=cq
Change-Id: I59c401d228f81a52c28d80e9db9718d41a255015
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/2078962
Reviewed-by: LaMont Jones <lamontjones@chromium.org>
Reviewed-by: Michael Mortensen <mmortensen@google.com>
Commit-Queue: Alex Klein <saklein@chromium.org>
Tested-by: Alex Klein <saklein@chromium.org>
diff --git a/scripts/build_api.py b/scripts/build_api.py
index fadf67c..727c2e3 100644
--- a/scripts/build_api.py
+++ b/scripts/build_api.py
@@ -10,20 +10,17 @@
import os
import sys
-from google.protobuf import json_format
-
from chromite.api import api_config as api_config_lib
from chromite.api import controller
+from chromite.api import message_util
from chromite.api import router as router_lib
from chromite.api.gen.chromite.api import build_api_config_pb2
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
-from chromite.lib import osutils
from chromite.lib import tee
from chromite.utils import matching
-
assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
@@ -34,18 +31,38 @@
parser.add_argument(
'service_method',
help='The "chromite.api.Service/Method" that is being called.')
- parser.add_argument(
+ # Input arguments.
+ input_args = parser.add_mutually_exclusive_group(required=True)
+ input_args.add_argument(
+ '--input-binary',
+ type='path',
+ help='Path to the protobuf binary serialization of the input message.')
+ input_args.add_argument(
'--input-json',
type='path',
help='Path to the JSON serialized input argument protobuf message.')
+ # Output options.
+ parser.add_argument(
+ '--output-binary',
+ type='path',
+ help='The path to which the protobuf binary serialization of the '
+ 'response message should be written.')
parser.add_argument(
'--output-json',
type='path',
- help='The path to which the result protobuf message should be written.')
- parser.add_argument(
+ help='The path to which the JSON serialization of the response message '
+ 'should be written.')
+ # Config options.
+ config_args = parser.add_mutually_exclusive_group()
+ config_args.add_argument(
+ '--config-binary',
+ type='path',
+ help='The path to the protobuf binary serialization of the Build API '
+ 'call configs.')
+ config_args.add_argument(
'--config-json',
type='path',
- help='The path to the Build API call configs.')
+ help='The path to the JSON encoded Build API call configs.')
# TODO(crbug.com/1040978): Remove after usages removed.
parser.add_argument(
'--tee-log',
@@ -86,30 +103,59 @@
opts.service = parts[0]
opts.method = parts[1]
- # --input-json and --output-json validation.
- if not opts.input_json or not opts.output_json:
- parser.error('--input-json and --output-json are both required.')
+ # Input and output validation.
+ if not opts.output_binary and not opts.output_json:
+ parser.error('At least one output file must be specified.')
- if not os.path.exists(opts.input_json):
+ if not os.path.exists(opts.input_binary or opts.input_json):
parser.error('Input file does not exist.')
config_msg = build_api_config_pb2.BuildApiConfig()
if opts.config_json:
+ handler = message_util.get_message_handler(opts.config_json,
+ message_util.FORMAT_JSON)
+ else:
+ handler = message_util.get_message_handler(opts.config_binary,
+ message_util.FORMAT_BINARY)
+
+ if opts.config_json or opts.config_binary:
+ # We have been given a config, so read it.
try:
- json_format.Parse(osutils.ReadFile(opts.config_json), config_msg,
- ignore_unknown_fields=True)
- except IOError as e:
- parser.error(e)
+ handler.read_into(config_msg)
+ except message_util.Error as e:
+ parser.error(str(e))
opts.config = api_config_lib.build_config_from_proto(config_msg)
+ opts.config_handler = handler
opts.Freeze()
return opts
+def _get_io_handlers(opts):
+ """Build the input and output handlers."""
+ if opts.input_binary:
+ input_handler = message_util.get_message_handler(opts.input_binary,
+ message_util.FORMAT_BINARY)
+ else:
+ input_handler = message_util.get_message_handler(opts.input_json,
+ message_util.FORMAT_JSON)
+
+ output_handlers = []
+ if opts.output_binary:
+ handler = message_util.get_message_handler(opts.output_binary,
+ message_util.FORMAT_BINARY)
+ output_handlers.append(handler)
+ if opts.output_json:
+ handler = message_util.get_message_handler(opts.output_json,
+ message_util.FORMAT_JSON)
+ output_handlers.append(handler)
+
+ return input_handler, output_handlers
+
+
def main(argv):
with cros_build_lib.ContextManagerStack() as stack:
-
router = router_lib.GetRouter()
opts = _ParseArgs(argv, router)
@@ -130,9 +176,11 @@
# correct return code here.
return controller.RETURN_CODE_INVALID_INPUT
+ input_handler, output_handlers = _get_io_handlers(opts)
+
try:
- return router.Route(opts.service, opts.method, opts.input_json,
- opts.output_json, opts.config)
+ return router.Route(opts.service, opts.method, opts.config, input_handler,
+ output_handlers, opts.config_handler)
except router_lib.Error as e:
# Handle router_lib.Error derivatives nicely, but let anything else bubble
# up.