forked from TrueCloudLab/frostfs-testlib
88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
import os
|
|
import re
|
|
from typing import Any
|
|
|
|
import yaml
|
|
|
|
from frostfs_testlib import reporter
|
|
from frostfs_testlib.shell.interfaces import CommandOptions, Shell
|
|
from frostfs_testlib.storage.configuration.interfaces import ServiceConfigurationYml
|
|
|
|
|
|
def extend_dict(extend_me: dict, extend_by: dict):
|
|
if isinstance(extend_by, dict):
|
|
for k, v in extend_by.items():
|
|
if k in extend_me:
|
|
extend_dict(extend_me.get(k), v)
|
|
else:
|
|
extend_me[k] = v
|
|
else:
|
|
extend_me += extend_by
|
|
|
|
|
|
class ServiceConfiguration(ServiceConfigurationYml):
|
|
def __init__(self, service_name: str, shell: Shell, config_dir: str, main_config_path: str) -> None:
|
|
self.service_name = service_name
|
|
self.shell = shell
|
|
self.main_config_path = main_config_path
|
|
self.confd_path = os.path.join(config_dir, "conf.d")
|
|
self.custom_file = os.path.join(self.confd_path, "99_changes.yml")
|
|
|
|
def _path_exists(self, path: str) -> bool:
|
|
return not self.shell.exec(f"test -e {path}", options=CommandOptions(check=False)).return_code
|
|
|
|
def _get_config_files(self):
|
|
config_files = [self.main_config_path]
|
|
|
|
if self._path_exists(self.confd_path):
|
|
files = self.shell.exec(f"find {self.confd_path} -type f").stdout.strip().split()
|
|
# Sorting files in backwards order from latest to first one
|
|
config_files.extend(sorted(files, key=lambda x: -int(re.findall("^\d+", os.path.basename(x))[0])))
|
|
|
|
return config_files
|
|
|
|
def _get_configuration(self, config_files: list[str]) -> dict:
|
|
if not config_files:
|
|
return [{}]
|
|
|
|
splitter = "+++++"
|
|
files_str = " ".join(config_files)
|
|
all_content = self.shell.exec(
|
|
f"echo Getting config files; for file in {files_str}; do (echo {splitter}; sudo cat ${{file}}); done"
|
|
).stdout
|
|
files_content = all_content.split("+++++")[1:]
|
|
files_data = [yaml.safe_load(file_content) for file_content in files_content]
|
|
|
|
mergedData = {}
|
|
for data in files_data:
|
|
extend_dict(mergedData, data)
|
|
|
|
return mergedData
|
|
|
|
def get(self, key: str) -> str | Any:
|
|
with reporter.step(f"Get {key} configuration value for {self.service_name}"):
|
|
config_files = self._get_config_files()
|
|
configuration = self._get_configuration(config_files)
|
|
result = self._find_option(key, configuration)
|
|
return result
|
|
|
|
def set(self, values: dict[str, Any]):
|
|
with reporter.step(f"Change configuration for {self.service_name}"):
|
|
if not self._path_exists(self.confd_path):
|
|
self.shell.exec(f"mkdir {self.confd_path}")
|
|
|
|
if self._path_exists(self.custom_file):
|
|
data = self._get_configuration([self.custom_file])
|
|
else:
|
|
data = {}
|
|
|
|
for key, value in values.items():
|
|
self._set_option(key, value, data)
|
|
|
|
content = yaml.dump(data)
|
|
self.shell.exec(f"echo '{content}' | sudo tee {self.custom_file}")
|
|
self.shell.exec(f"chmod 777 {self.custom_file}")
|
|
|
|
def revert(self):
|
|
with reporter.step(f"Revert changed options for {self.service_name}"):
|
|
self.shell.exec(f"rm -rf {self.custom_file}")
|