def test_load_yaml_str_input_check(mocker): data = 'some-data' run_m = mocker.patch.object(utils.yaml, 'safe_load', autospec=True) utils.load_yaml_str(data) run_m.assert_called_once_with(data)
def test_load_yaml_str_raises_exception(mocker, patch_logging): data = 'some-data' mocker.patch.object(utils.yaml, 'safe_load', autospec=True, side_effect=yaml.YAMLError) with pytest.raises(errors.BadPillarDataError): utils.load_yaml_str(data)
def test_load_yaml_str_output_check(mocker): in_data = 'some-in-data' out_data = 'some-out-data' mocker.patch.object( utils.yaml, 'safe_load', autospec=True, return_value=out_data ) assert utils.load_yaml_str(in_data) == out_data
def build(self): res = {} # render the template as a very first step config_str = self.render() # deserialize config_spec = utils.load_yaml_str(config_str) # verify that different rendering results are not mixed here ctx = config_spec.pop(config.MiniAPISpecFields.CTX.value, None) if ctx and (ctx != self.render_ctx): raise ValueError( f"the spec is already rendered for a different context: {ctx}") self._version = config_spec.pop(config.MiniAPISpecFields.VERSION.value, None) if self._version is None: logger.info("Legacy (initial) version is being parsed") self._version = config.MiniAPISpecVersions.INITIAL.value support_bundle = config_spec.pop( config.MiniAPISpecFields.SUPPORT_BUNDLE.value, None) if support_bundle: support_bundle = HookSpecSupportBundle(support_bundle) # format validation: single top level key if len(config_spec) != 1: logger.warning( f"multiple components on the top level of '{self.spec}':" f" {list(config_spec)}") # mark version res[config.MiniAPISpecFields.VERSION.value] = self._version # store the rendered ctx res[config.MiniAPISpecFields.CTX.value] = self.render_ctx # restore support bundle data if support_bundle: res[config.MiniAPISpecFields.SUPPORT_BUNDLE.value] = ( support_bundle.spec(normalize=self.normalize)) for sw, sw_spec in config_spec.items(): # format validation: top level value is a dict if not isinstance(sw_spec, dict): raise TypeError( "a dictionary is expected as a top level value," f" provided {type(sw_spec)}") # store the sw spec res[sw] = self._build_spec(sw_spec) return res
def load_metadata(self): """ Load the metadata from metadata url Returns ------- dict: dictionary with Cortx repository metadata (content of RELEASE.INFO file) """ try: if self.metadata_uri.is_local: metadata = utils.load_yaml(self.metadata_uri.path) else: r = requests.get(str(self.metadata_uri)) metadata = utils.load_yaml_str(r.content.decode("utf-8")) except Exception as exc: raise errors.SWUpdateRepoSourceError( str(self.metadata_uri), f"Failed to load '{self.metadata_uri}' file: {exc}") return metadata
def test_swupgrade_r2_offline(setup_hosts, mock_system_cmds, ssh_client, salt_ready, request): # upgrade ISO prepared (with mocks): # - TODO HA setup.yaml includes pre/post flag on cluster level # FIXME hard-coded upgrade_iso = '/var/lib/seagate/cortx/provisioner/local/cortx_repos/upgrade_mock_2.1.0.iso' # noqa: E501 run_host = setup_hosts[0] old_ver = '2.0.0-177' new_ver = '2.1.0-177' # logic (HAPPY PATH): run_host.check_output(f"provisioner set_swupgrade_repo {upgrade_iso}") run_host.check_output("provisioner sw_upgrade --offline") # CHECKS # CLUSTER level # new Cortx version is running # FIXME hard-coded metadata_str = run_host.check_output( "provisioner release get_release --out yaml") metadata = utils.load_yaml_str(metadata_str)['ret'] assert CortxRelease(metadata=metadata).version == new_ver # - new provisioner API vesion was called to manage the logic # with --noprepare flag # - node level logic was applied for all the nodes concurrently # - cluster level logic: # - HA standby # - HA pre upgrade # - cluster stop # - node level logic # - HA post upgrade # - cluster start # - NODE level # - upgrade for sw was applied in predefined order # - mini APIs: (TODO separate test for setup.yaml spec) # - called on NODE level # - HA: were called for CLUSTER level as well # # FIXME hard-coded mock output def mock_str(flow, level, hook, old_ver=None, new_ver=None): res = (f"{flow} {level} {hook} " f"PRVSNR_MINI_FLOW={flow}," f"PRVSNR_MINI_LEVEL={level}," f"PRVSNR_MINI_HOOK={hook}") if old_ver: res += f",CORTX_VERSION={old_ver}" if new_ver: res += f",CORTX_UPGRADE_VERSION={new_ver}" return res assert (run_host.check_output( "grep ha: /tmp/mock.log | awk '{print $3 FS $4 FS $6 FS $7}'" ) == ( f"{mock_str('upgrade-offline', 'cluster', 'backup')}\n" f"{mock_str('upgrade-offline', 'cluster', 'pre-upgrade', old_ver, new_ver)}\n" # noqa: E501 f"{mock_str('upgrade-offline', 'node', 'backup')}\n" f"{mock_str('upgrade-offline', 'node', 'pre-upgrade', old_ver, new_ver)}\n" # noqa: E501 f"{mock_str('upgrade-offline', 'node', 'post-upgrade', old_ver, new_ver)}\n" # noqa: E501 f"{mock_str('upgrade-offline', 'cluster', 'post-upgrade', old_ver, new_ver)}" # noqa: E501 )) # other nodes should receive only node level events for host in setup_hosts[1:]: assert (host.check_output( "grep ha: /tmp/mock.log | awk '{print $3 FS $4 FS $6 FS $7}'" ) == ( f"{mock_str('upgrade-offline', 'node', 'backup')}\n" f"{mock_str('upgrade-offline', 'node', 'pre-upgrade', old_ver, new_ver)}\n" # noqa: E501 f"{mock_str('upgrade-offline', 'node', 'post-upgrade', old_ver, new_ver)}" # noqa: E501 ))