From ce85ac20a90656beed2fb857269f9ae36d9734af Mon Sep 17 00:00:00 2001 From: Lili Nie Date: Fri, 27 Sep 2024 07:21:02 -0400 Subject: [PATCH] rename _normalize_user_data,and add doc --- tmt/steps/provision/artemis.py | 6 +-- tmt/steps/provision/mrack.py | 8 ++-- tmt/utils/__init__.py | 67 ++++++++++++++++++++-------------- 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/tmt/steps/provision/artemis.py b/tmt/steps/provision/artemis.py index 6c7253ad9d..35e611431b 100644 --- a/tmt/steps/provision/artemis.py +++ b/tmt/steps/provision/artemis.py @@ -15,9 +15,9 @@ from tmt.utils import ( ProvisionError, UpdatableMessage, - _normalize_user_data, dict_to_yaml, field, + normalize_value_optional_string_dict, retry_session, ) @@ -154,14 +154,14 @@ class ArtemisGuestData(tmt.steps.provision.GuestSshData): metavar='KEY=VALUE', help='Optional data to attach to guest.', multiple=True, - normalize=_normalize_user_data) + normalize=normalize_value_optional_string_dict) kickstart: dict[str, str] = field( default_factory=dict, option='--kickstart', metavar='KEY=VALUE', help='Optional Beaker kickstart to use when provisioning the guest.', multiple=True, - normalize=_normalize_user_data) + normalize=normalize_value_optional_string_dict) log_type: list[str] = field( default_factory=list, diff --git a/tmt/steps/provision/mrack.py b/tmt/steps/provision/mrack.py index bf3c2193dc..0cd1d9b9b1 100644 --- a/tmt/steps/provision/mrack.py +++ b/tmt/steps/provision/mrack.py @@ -21,7 +21,6 @@ ProvisionError, ShellScript, UpdatableMessage, - _normalize_user_data, field, ) @@ -683,8 +682,6 @@ def _translate_tmt_hw(self, hw: tmt.hardware.Hardware) -> dict[str, Any]: def create_host_requirement(self, host: CreateJobParameters) -> dict[str, Any]: """ Create single input for Beaker provisioner """ - - host["beaker"]["ks_append"] = host.get('kickstart') req: dict[str, Any] = super().create_host_requirement(dataclasses.asdict(host)) if host.hardware and host.hardware.constraint: @@ -778,7 +775,7 @@ class BeakerGuestData(tmt.steps.provision.GuestSshData): metavar='KEY=VALUE', help='Optional Beaker kickstart to use when provisioning the guest.', multiple=True, - normalize=_normalize_user_data) + normalize=tmt.utils.normalize_value_optional_string_dict) beaker_job_owner: Optional[str] = field( default=None, @@ -823,6 +820,7 @@ class CreateJobParameters: hardware: Optional[tmt.hardware.Hardware] whiteboard: Optional[str] beaker_job_owner: Optional[str] + beaker: dict[str, str] group: str = 'linux' @@ -1001,7 +999,7 @@ def _create(self, tmt_name: str) -> None: name=f'{self.image}-{self.arch}', whiteboard=self.whiteboard or tmt_name, beaker_job_owner=self.beaker_job_owner, - kickstart=self.kickstart) + beaker={'ks_append': self.kickstart}) try: response = self.api.create(data) diff --git a/tmt/utils/__init__.py b/tmt/utils/__init__.py index e3750b3079..619254df0d 100644 --- a/tmt/utils/__init__.py +++ b/tmt/utils/__init__.py @@ -74,34 +74,6 @@ from tmt._compat.typing import Self, TypeAlias -def _normalize_user_data( - key_address: str, - raw_value: Any, - logger: tmt.log.Logger) -> dict[str, str]: - if isinstance(raw_value, dict): - return { - str(key).strip(): str(value).strip() for key, value in raw_value.items() - } - - if isinstance(raw_value, (list, tuple)): - user_data = {} - - for datum in raw_value: - try: - key, value = datum.split('=', 1) - - except ValueError as exc: - raise tmt.utils.NormalizationError( - key_address, datum, 'a KEY=VALUE string') from exc - - user_data[key.strip()] = value.strip() - - return user_data - - raise tmt.utils.NormalizationError( - key_address, value, 'a dictionary or a list of KEY=VALUE strings') - - def configure_optional_constant(default: Optional[int], envvar: str) -> Optional[int]: """ Deduce the actual value of a global constant which may be left unset. @@ -5417,6 +5389,45 @@ def normalize_shell_script( raise NormalizationError(key_address, value, 'a string') +def normalize_value_optional_string_dict( + key_address: str, + raw_value: Any, + logger: tmt.log.Logger) -> dict[str, str]: + """ + Normalize a dict-or-list-or-tuple input value. + + :param raw_value: dict, or list, or tuple. + raw_value could be a dict: + {'metadata': 'no_autopart'; + 'script': 'autopart --type lvm' } + or, list/tuple contains KEY=VALUE strings: + ['metadata=no_autopart', 'script=autopart --type lvm'] + """ + + if isinstance(raw_value, dict): + return { + str(key).strip(): str(value).strip() for key, value in raw_value.items() + } + + if isinstance(raw_value, (list, tuple)): + user_data = {} + + for datum in raw_value: + try: + key, value = datum.split('=', 1) + + except ValueError as exc: + raise tmt.utils.NormalizationError( + key_address, datum, 'a KEY=VALUE string') from exc + + user_data[key.strip()] = value.strip() + + return user_data + + raise tmt.utils.NormalizationError( + key_address, value, 'a dictionary or a list of KEY=VALUE strings') + + class NormalizeKeysMixin(_CommonBase): """ Mixin adding support for loading fmf keys into object attributes.