Skip to content

Commit 5013853

Browse files
Jorresblinkov
authored andcommitted
Add --backport-to-template functionality (#15483)
1 parent 1febe01 commit 5013853

File tree

5 files changed

+91
-11
lines changed

5 files changed

+91
-11
lines changed

ydb/tools/cfg/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ def __init__(self, template, host_info_provider, validator=None, database=None,
304304
self.table_profiles_config = self.__cluster_description.get("table_profiles_config")
305305
self.http_proxy_config = self.__cluster_description.get("http_proxy_config")
306306
self.blob_storage_config = self.__cluster_description.get("blob_storage_config")
307+
self.bootstrap_config = self.__cluster_description.get("bootstrap_config")
307308
self.memory_controller_config = self.__cluster_description.get("memory_controller_config")
308309
self.s3_proxy_resolver_config = self.__cluster_description.get("s3_proxy_resolver_config")
309310
self.channel_profile_config = self.__cluster_description.get("channel_profile_config")

ydb/tools/cfg/bin/__main__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ydb.tools.cfg.configurator_setup import get_parser, parse_optional_arguments
1111
from ydb.tools.cfg.dynamic import DynamicConfigGenerator
1212
from ydb.tools.cfg.static import StaticConfigGenerator
13-
from ydb.tools.cfg.utils import write_to_file
13+
from ydb.tools.cfg.utils import write_to_file, backport
1414
from ydb.tools.cfg.walle import NopHostsInformationProvider, WalleHostsInformationProvider
1515
from ydb.tools.cfg.k8s_api import K8sApiHostsInformationProvider
1616

@@ -76,6 +76,9 @@ def cfg_generate(args):
7676
for cfg_name, cfg_value in all_configs.items():
7777
write_to_file(os.path.join(args.output_dir, cfg_name), cfg_value)
7878

79+
if args.backport_to_template:
80+
backport(args.cluster_description, all_configs["config.yaml"], ["blob_storage_config"])
81+
7982

8083
def main():
8184
parser = get_parser(cfg_generate)

ydb/tools/cfg/configurator_setup.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,9 @@ def get_parser(generate_func, extra_cfg_arguments=[]):
105105
'--nfs-control', action='store_true', help='Forces cfg command to generate NFS Control configuration'
106106
)
107107

108+
parser_cfg.add_argument('--backport-to-template',
109+
action='store_true',
110+
help='Backport blob_storage_config and similar sections to template after generation')
111+
108112
parser_cfg.set_defaults(func=generate_func)
109113
return parser

ydb/tools/cfg/static.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ def get_normalized_config(self):
488488
if self.__cluster_details.s3_proxy_resolver_config is not None:
489489
normalized_config["s3_proxy_resolver_config"] = self.__cluster_details.s3_proxy_resolver_config
490490

491-
if self.__cluster_details.blob_storage_config is not None:
491+
if not utils.need_generate_bs_config(self.__cluster_details.blob_storage_config):
492492
normalized_config["blob_storage_config"] = self.__cluster_details.blob_storage_config
493493
else:
494494
blobstorage_config_service_set = normalized_config["blob_storage_config"]["service_set"]
@@ -807,18 +807,25 @@ def __system_tablets(self):
807807
def __generate_boot_txt(self):
808808
self.__proto_configs["boot.txt"] = bootstrap_pb2.TBootstrap()
809809

810+
# New style `config.yaml`, allow specifying bootstrap_config
811+
if self.__cluster_details.bootstrap_config is not None:
812+
template_proto = bootstrap_pb2.TBootstrap()
813+
utils.wrap_parse_dict(self.__cluster_details.bootstrap_config, template_proto)
814+
self.__proto_configs["boot.txt"].MergeFrom(template_proto)
815+
else:
816+
# Old style `template.yaml`, just get random fields from top-level of `template.yaml`
817+
if self.__cluster_details.shared_cache_memory_limit is not None:
818+
boot_txt = self.__proto_configs["boot.txt"]
819+
boot_txt.SharedCacheConfig.MemoryLimit = self.__cluster_details.shared_cache_memory_limit
820+
shared_cache_size = self.__cluster_details.pq_shared_cache_size
821+
if shared_cache_size is not None:
822+
boot_txt = self.__proto_configs["boot.txt"]
823+
boot_txt.NodeLimits.PersQueueNodeConfig.SharedCacheSizeMb = shared_cache_size
824+
810825
for tablet_type, tablet_count in self.__system_tablets:
811826
for index in range(int(tablet_count)):
812827
self.__add_tablet(tablet_type, index, self.__cluster_details.system_tablets_node_ids)
813828

814-
if self.__cluster_details.shared_cache_memory_limit is not None:
815-
boot_txt = self.__proto_configs["boot.txt"]
816-
boot_txt.SharedCacheConfig.MemoryLimit = self.__cluster_details.shared_cache_memory_limit
817-
shared_cache_size = self.__cluster_details.pq_shared_cache_size
818-
if shared_cache_size is not None:
819-
boot_txt = self.__proto_configs["boot.txt"]
820-
boot_txt.NodeLimits.PersQueueNodeConfig.SharedCacheSizeMb = shared_cache_size
821-
822829
def __generate_bs_txt(self):
823830
self.__proto_configs["bs.txt"] = config_pb2.TBlobStorageConfig()
824831
bs_format_config = config_pb2.TBlobStorageFormatConfig()
@@ -864,7 +871,7 @@ def __generate_bs_txt(self):
864871
dc_enumeration = {}
865872

866873
if not self.__cluster_details.get_service("static_groups"):
867-
if self.__cluster_details.blob_storage_config:
874+
if not utils.need_generate_bs_config(self.__cluster_details.blob_storage_config):
868875
return
869876
self.__proto_configs["bs.txt"] = self._read_generated_bs_config(
870877
str(self.__cluster_details.static_erasure),
@@ -873,6 +880,13 @@ def __generate_bs_txt(self):
873880
str(self.__cluster_details.fail_domain_type),
874881
bs_format_config,
875882
)
883+
884+
# Merging generated static group config with other keys
885+
if self.__cluster_details.blob_storage_config is not None:
886+
template_proto = config_pb2.TBlobStorageConfig()
887+
utils.wrap_parse_dict(self.__cluster_details.blob_storage_config, template_proto)
888+
self.__proto_configs["bs.txt"].MergeFrom(template_proto)
889+
876890
if self.__cluster_details.nw_cache_file_path is not None:
877891
self.__proto_configs["bs.txt"].CacheFilePath = self.__cluster_details.nw_cache_file_path
878892
return

ydb/tools/cfg/utils.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
import random
55
import string
6+
import yaml
67

78
import six
89
from google.protobuf import text_format, json_format
@@ -165,6 +166,10 @@ def get_camel_case_string(snake_str):
165166
'NtoSelect': 'NToSelect',
166167
'Ssid': 'SSId',
167168
'Sids': 'SIDs',
169+
'GroupId': 'GroupID',
170+
'NodeId': 'NodeID',
171+
'DiskId': 'DiskID',
172+
'SlotId': 'SlotID',
168173
}
169174
for k, v in abbreviations.items():
170175
camelCased = camelCased.replace(k, v)
@@ -179,3 +184,56 @@ def convert_keys(data):
179184
return data
180185

181186
json_format.ParseDict(convert_keys(dictionary), proto)
187+
188+
189+
# This function does some extra work, text processing to ensure no extra diff is
190+
# created when backporting sections like blob_storage_config. If we parse
191+
# template file and dump it again, there will be a lot of meaningless diff
192+
# in formatting, which is undesirable.
193+
def backport(template_path, config_yaml, backported_sections):
194+
config_data = yaml.safe_load(config_yaml)
195+
196+
with open(template_path, 'r') as file:
197+
lines = file.readlines()
198+
199+
for section_key in backported_sections:
200+
section = config_data.get(section_key)
201+
202+
if section is None:
203+
raise KeyError(f"The key '{section_key}' was not found in config_yaml")
204+
205+
new_section_yaml = yaml.safe_dump({section_key: section}, default_flow_style=False).splitlines(True)
206+
new_section_yaml.append(os.linesep)
207+
208+
start_index = None
209+
end_index = None
210+
211+
for i, line in enumerate(lines):
212+
if line.startswith(f"{section_key}:"):
213+
start_index = i
214+
break
215+
216+
if start_index is not None:
217+
end_index = start_index + 1
218+
while end_index < len(lines):
219+
line = lines[end_index]
220+
if line.strip() and not line.startswith(' ') and not line.startswith('#'): # Check for a top-level key
221+
break
222+
end_index += 1
223+
224+
lines = lines[:start_index] + new_section_yaml + lines[end_index:]
225+
else:
226+
lines.extend(new_section_yaml)
227+
228+
with open(template_path, 'w') as file:
229+
file.writelines(lines)
230+
231+
232+
def need_generate_bs_config(template_bs_config):
233+
# We need to generate blob_storage_config if template file does not contain static group:
234+
# blob_storage_config.service_set.groups
235+
236+
if template_bs_config is None:
237+
return True
238+
239+
return template_bs_config.get("service_set", {}).get("groups") is None

0 commit comments

Comments
 (0)