boxster: update script to parse FlatConfigs into UFS datastore

Added capability to parse and extract FlatConfigs from FlatConfigList
into UFS datastore. IDs are based on the program and design ID values.

BUG=b/186663540
TEST=manual testing

Change-Id: Ia27cbde0349f55faae3d6e19ad25b6464f8a858c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/config/+/3108610
Commit-Queue: Sean McAllister <smcallis@google.com>
Reviewed-by: Sean McAllister <smcallis@google.com>
Reviewed-by: Xixuan Wu <xixuan@chromium.org>
diff --git a/payload_utils/config_to_datastore.py b/payload_utils/config_to_datastore.py
index 958c1f0..7f0cea9 100755
--- a/payload_utils/config_to_datastore.py
+++ b/payload_utils/config_to_datastore.py
@@ -12,6 +12,7 @@
 
 1. ConfigBundleList from 'hw_design/generated/configs.jsonproto'
 2. DutAttributeList from 'dut_attributes/generated/dut_attributes.jsonproto'
+3. FlatConfigList from 'hw_design/generated/flattened.jsonproto'
 
 The lists are parsed and individual entities are extracted. Using the datastore
 client specified, it encodes the protos as datastore entities and stores them
@@ -32,6 +33,8 @@
 CB_OUTPUT_TYPE = 'chromiumos.config.payload.ConfigBundle'
 DA_INPUT_TYPE = 'chromiumos.test.api.DutAttributeList'
 DA_OUTPUT_TYPE = 'chromiumos.test.api.DutAttribute'
+FC_INPUT_TYPE = 'chromiumos.config.payload.FlatConfigList'
+FC_OUTPUT_TYPE = 'chromiumos.config.payload.FlatConfig'
 
 # UFS services
 UFS_DEV_PROJECT = 'unified-fleet-system-dev'
@@ -40,6 +43,7 @@
 # datastore constants
 CONFIG_BUNDLE_KIND = 'ConfigBundle'
 DUT_ATTRIBUTE_KIND = 'DutAttribute'
+FLAT_CONFIG_KIND = 'FlatConfig'
 
 
 def get_ufs_project(env):
@@ -51,7 +55,7 @@
   raise RuntimeError('get_ufs_project: environment %s not supported' % env)
 
 
-def generate_entity_id(bundle):
+def generate_config_bundle_id(bundle):
   """Generate ConfigBundleEntity id as ${program_id}-${design_id}."""
   return bundle.design_list[0].program_id.value + '-' + bundle.design_list[
       0].id.value
@@ -65,25 +69,49 @@
       protodb.GetSymbol(CB_INPUT_TYPE)(), cb_list_path)
 
   for config_bundle in cb_list.values:
-    update_config_bundle(config_bundle, get_ufs_project(env))
+    update_config(config_bundle, get_ufs_project(env), flat=False)
 
 
-def update_config_bundle(bundle, project):
-  """Take a ConfigBundle and store it in the UFS datastore as a ConfigBundleEntity."""
-  eid = generate_entity_id(bundle)
-  logging.info('update_config_bundle: handling %s', eid)
+def generate_flat_config_id(bundle):
+  """Generate FlatConfigEntity id as ${program_id}-${design_id}-${design_config_id}
+  if design_config_id is available. Else ${program_id}-${design_id}."""
+  if bundle.hw_design_config.id.value:
+    return bundle.hw_design.program_id.value + '-' + bundle.hw_design.id.value \
+    + '-' + bundle.hw_design_config.id.value
+  return bundle.hw_design.program_id.value + '-' + bundle.hw_design.id.value
+
+
+def handle_flat_config_list(fc_list_path, env):
+  """Take a path to a FlatConfigList, iterate through the list and store into
+  UFS datastore based on env.
+  """
+  fc_list = io_utils.read_json_proto(
+      protodb.GetSymbol(FC_INPUT_TYPE)(), fc_list_path)
+
+  for flat_config in fc_list.values:
+    update_config(flat_config, get_ufs_project(env), flat=True)
+
+
+def update_config(config, project, flat=False):
+  """Take a ConfigBundle or FlatConfig and store it an an entity in the UFS datastore."""
+  if flat:
+    kind = FLAT_CONFIG_KIND
+    eid = generate_flat_config_id(config)
+  else:
+    kind = CONFIG_BUNDLE_KIND
+    eid = generate_config_bundle_id(config)
+  logging.info('update_config: handling %s', eid)
 
   client = datastore.Client(project=project,)
-  key = client.key(CONFIG_BUNDLE_KIND, eid)
+  key = client.key(kind, eid)
   entity = datastore.Entity(
       key=key,
       exclude_from_indexes=['ConfigData'],
   )
-  entity['ConfigData'] = bundle.SerializeToString()
+  entity['ConfigData'] = config.SerializeToString()
   entity['updated'] = datetime.datetime.now()
 
-  logging.info('update_config_bundle: putting entity into datastore for %s',
-               eid)
+  logging.info('update_config: putting entity into datastore for %s', eid)
   client.put(entity)
 
 
@@ -139,3 +167,5 @@
                             options.env)
   handle_dut_attribute_list("dut_attributes/generated/dut_attributes.jsonproto",
                             options.env)
+  handle_flat_config_list("hw_design/generated/flattened.jsonproto",
+                          options.env)