blob: 7f0cea9456db6d0ea7609c53d317866e0578cdf3 [file] [log] [blame]
Justin Suenf9095ee2021-06-25 18:25:44 +00001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# Copyright 2021 The Chromium OS Authors. All rights reserved.
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
Justin Suen84529bd2021-07-22 18:06:48 +00007"""Marshal ConfigBundles and DutAttributes. Store them into the UFS datastore
8through the Google datastore API.
Justin Suenf9095ee2021-06-25 18:25:44 +00009
Justin Suen84529bd2021-07-22 18:06:48 +000010By default, this script converts a few config-related protos into datastore
11entities:
12
131. ConfigBundleList from 'hw_design/generated/configs.jsonproto'
142. DutAttributeList from 'dut_attributes/generated/dut_attributes.jsonproto'
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000153. FlatConfigList from 'hw_design/generated/flattened.jsonproto'
Justin Suen84529bd2021-07-22 18:06:48 +000016
17The lists are parsed and individual entities are extracted. Using the datastore
18client specified, it encodes the protos as datastore entities and stores them
19into the UFS datastore.
Justin Suenf9095ee2021-06-25 18:25:44 +000020"""
21
22import argparse
23import datetime
24import logging
25
26from google.cloud import datastore
27
28from checker import io_utils
29from common import proto_utils
30
31# type constants
Justin Suen84529bd2021-07-22 18:06:48 +000032CB_INPUT_TYPE = 'chromiumos.config.payload.ConfigBundleList'
33CB_OUTPUT_TYPE = 'chromiumos.config.payload.ConfigBundle'
34DA_INPUT_TYPE = 'chromiumos.test.api.DutAttributeList'
35DA_OUTPUT_TYPE = 'chromiumos.test.api.DutAttribute'
Justin Suen5aaa7cd2021-09-01 08:55:53 +000036FC_INPUT_TYPE = 'chromiumos.config.payload.FlatConfigList'
37FC_OUTPUT_TYPE = 'chromiumos.config.payload.FlatConfig'
Justin Suenf9095ee2021-06-25 18:25:44 +000038
39# UFS services
40UFS_DEV_PROJECT = 'unified-fleet-system-dev'
41UFS_PROD_PROJECT = 'unified-fleet-system'
42
43# datastore constants
44CONFIG_BUNDLE_KIND = 'ConfigBundle'
Justin Suen84529bd2021-07-22 18:06:48 +000045DUT_ATTRIBUTE_KIND = 'DutAttribute'
Justin Suen5aaa7cd2021-09-01 08:55:53 +000046FLAT_CONFIG_KIND = 'FlatConfig'
Justin Suenf9095ee2021-06-25 18:25:44 +000047
48
49def get_ufs_project(env):
50 """Return project name based on env argument."""
51 if env == 'dev':
52 return UFS_DEV_PROJECT
53 if env == 'prod':
54 return UFS_PROD_PROJECT
55 raise RuntimeError('get_ufs_project: environment %s not supported' % env)
56
57
Justin Suen5aaa7cd2021-09-01 08:55:53 +000058def generate_config_bundle_id(bundle):
Justin Suenf9095ee2021-06-25 18:25:44 +000059 """Generate ConfigBundleEntity id as ${program_id}-${design_id}."""
60 return bundle.design_list[0].program_id.value + '-' + bundle.design_list[
61 0].id.value
62
63
Justin Suen84529bd2021-07-22 18:06:48 +000064def handle_config_bundle_list(cb_list_path, env):
65 """Take a path to a ConfigBundleList, iterate through the list and store into
66 UFS datastore based on env.
67 """
68 cb_list = io_utils.read_json_proto(
69 protodb.GetSymbol(CB_INPUT_TYPE)(), cb_list_path)
70
71 for config_bundle in cb_list.values:
Justin Suen5aaa7cd2021-09-01 08:55:53 +000072 update_config(config_bundle, get_ufs_project(env), flat=False)
Justin Suen84529bd2021-07-22 18:06:48 +000073
74
Justin Suen5aaa7cd2021-09-01 08:55:53 +000075def generate_flat_config_id(bundle):
76 """Generate FlatConfigEntity id as ${program_id}-${design_id}-${design_config_id}
77 if design_config_id is available. Else ${program_id}-${design_id}."""
78 if bundle.hw_design_config.id.value:
79 return bundle.hw_design.program_id.value + '-' + bundle.hw_design.id.value \
80 + '-' + bundle.hw_design_config.id.value
81 return bundle.hw_design.program_id.value + '-' + bundle.hw_design.id.value
82
83
84def handle_flat_config_list(fc_list_path, env):
85 """Take a path to a FlatConfigList, iterate through the list and store into
86 UFS datastore based on env.
87 """
88 fc_list = io_utils.read_json_proto(
89 protodb.GetSymbol(FC_INPUT_TYPE)(), fc_list_path)
90
91 for flat_config in fc_list.values:
92 update_config(flat_config, get_ufs_project(env), flat=True)
93
94
95def update_config(config, project, flat=False):
96 """Take a ConfigBundle or FlatConfig and store it an an entity in the UFS datastore."""
97 if flat:
98 kind = FLAT_CONFIG_KIND
99 eid = generate_flat_config_id(config)
100 else:
101 kind = CONFIG_BUNDLE_KIND
102 eid = generate_config_bundle_id(config)
103 logging.info('update_config: handling %s', eid)
Justin Suenf9095ee2021-06-25 18:25:44 +0000104
105 client = datastore.Client(project=project,)
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000106 key = client.key(kind, eid)
Justin Suenf9095ee2021-06-25 18:25:44 +0000107 entity = datastore.Entity(
108 key=key,
109 exclude_from_indexes=['ConfigData'],
110 )
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000111 entity['ConfigData'] = config.SerializeToString()
Justin Suenf9095ee2021-06-25 18:25:44 +0000112 entity['updated'] = datetime.datetime.now()
113
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000114 logging.info('update_config: putting entity into datastore for %s', eid)
Justin Suen84529bd2021-07-22 18:06:48 +0000115 client.put(entity)
116
117
118def handle_dut_attribute_list(dut_attr_list_path, env):
119 """Take a path to a DutAttributeList, iterate through the list and store into
120 UFS datastore based on env.
121 """
122 dut_attr_list = io_utils.read_json_proto(
123 protodb.GetSymbol(DA_INPUT_TYPE)(), dut_attr_list_path)
124
125 for dut_attribute in dut_attr_list.dut_attributes:
126 update_dut_attribute(dut_attribute, get_ufs_project(env))
127
128
129def update_dut_attribute(attr, project):
130 """Take a DutAttribute and store it in the UFS datastore as a DutAttributeEntity."""
131 eid = attr.id.value
132 logging.info('update_dut_attribute: handling %s', eid)
133
134 client = datastore.Client(project=project,)
135 key = client.key(DUT_ATTRIBUTE_KIND, eid)
136 entity = datastore.Entity(
137 key=key,
138 exclude_from_indexes=['AttributeData'],
139 )
140 entity['AttributeData'] = attr.SerializeToString()
141 entity['updated'] = datetime.datetime.now()
142
143 logging.info('update_dut_attribute: putting entity into datastore for %s',
144 eid)
145 client.put(entity)
Justin Suenf9095ee2021-06-25 18:25:44 +0000146
147
148if __name__ == '__main__':
149 logging.basicConfig(level=logging.INFO)
150 parser = argparse.ArgumentParser(
151 description=__doc__,
152 formatter_class=argparse.RawDescriptionHelpFormatter,
153 )
154
155 parser.add_argument(
Justin Suenf9095ee2021-06-25 18:25:44 +0000156 '--env',
157 type=str,
158 default='dev',
159 help='environment flag for UFS service',
160 )
161
162 # load database of protobuffer name -> Type
163 protodb = proto_utils.create_symbol_db()
Justin Suenf9095ee2021-06-25 18:25:44 +0000164 options = parser.parse_args()
Justin Suenf9095ee2021-06-25 18:25:44 +0000165
Justin Suen84529bd2021-07-22 18:06:48 +0000166 handle_config_bundle_list("hw_design/generated/configs.jsonproto",
167 options.env)
168 handle_dut_attribute_list("dut_attributes/generated/dut_attributes.jsonproto",
169 options.env)
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000170 handle_flat_config_list("hw_design/generated/flattened.jsonproto",
171 options.env)