Write utility to join ConfigBundle protos with legacy configs.

join_config_payloads.py will take generated ConfigBundle protos (in
jsonpb format), along with a HWID database and model.yaml files and
merge the information contained in all three to produce a new set of
ConfigBundle json protos.

BUG=chromium:1073073
TEST=manual

Change-Id: Id62709f9478bfc86b3b5ef9f18194bee57db60df
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/config/+/2222290
Commit-Queue: Sean McAllister <smcallis@google.com>
Tested-by: Sean McAllister <smcallis@google.com>
Reviewed-by: C Shapiro <shapiroc@chromium.org>
Reviewed-by: Andrew Lamb <andrewlamb@chromium.org>
diff --git a/payload_utils/checker/io_utils.py b/payload_utils/checker/io_utils.py
index 1d698af..7b50dcd 100644
--- a/payload_utils/checker/io_utils.py
+++ b/payload_utils/checker/io_utils.py
@@ -6,29 +6,54 @@
 import json
 import pathlib
 
+from typing import Any, Dict
+
 from chromiumos.config.payload import config_bundle_pb2
 
 from google.protobuf import json_format
+from google.protobuf.message import Message
+
+
+def write_message_json(message: Message, path: pathlib.Path, \
+                       default_fields=False):
+  """Take a Message and write it to a file as json.
+
+  Args:
+    message: protobuf message to write to file
+    path: output file write json to
+    default_fields: If true, include default values for fields
+  """
+  # ow this is a long parameter
+  opts = {'including_default_value_fields': default_fields, 'sort_keys': True}
+
+  with open(path, 'w') as outfile:
+    outfile.write(json_format.MessageToJson(message, **opts))
 
 
 def read_config(path: str) -> config_bundle_pb2.ConfigBundle:
-  """Reads a json proto from a file.
+  """Reads a ConfigBundle mesage from a jsonpb file.
 
-    Args:
-        path: Path to the json proto. See note above about deprecated repo
-        root behavior.
-    """
+  Args:
+    path: Path to the json proto. See note above about deprecated repo
+           root behavior.
+
+  Returns:
+    ConfigBundle parsed from file.
+  """
   project_config = config_bundle_pb2.ConfigBundle()
   with open(path, 'r') as f:
     json_format.Parse(f.read(), project_config)
   return project_config
 
 
-def read_model_sku_json(factory_dir: pathlib.Path) -> dict:
+def read_model_sku_json(factory_dir: pathlib.Path) -> Dict[str, Any]:
   """Reads and parses the model_sku.json file.
 
   Args:
-      factory_dir: Path to a project's factory dir.
+    factory_dir: Path to a project's factory dir.
+
+  Returns:
+    Parsed model_sku.json as a dict
   """
   with open(factory_dir.joinpath('generated', 'model_sku.json')) as f:
     return json.load(f)