From 669c6cce98b265cd4aaf98fb50ba1ad33e9cfc59 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sun, 5 Oct 2025 21:33:44 +0200 Subject: [PATCH] feat: use user_datas to load datas --- locale/rougail_user_data_bitwarden.pot | 26 +- src/rougail/user_data_bitwarden/data.py | 345 +++++++++--------- .../errors/bitwarden.json | 6 + .../makedict/bitwarden.json | 10 + .../errors/bitwarden.json | 6 + .../makedict/bitwarden.json | 8 + .../5_secret_calc_other_user_data/00-base.yml | 39 ++ .../00-base.yml | 35 ++ tests/test_load.py | 243 ++++++------ 9 files changed, 416 insertions(+), 302 deletions(-) create mode 100644 tests/results/5_secret_calc_other_user_data/errors/bitwarden.json create mode 100644 tests/results/5_secret_calc_other_user_data/makedict/bitwarden.json create mode 100644 tests/results/5_secret_calc_other_user_data2/errors/bitwarden.json create mode 100644 tests/results/5_secret_calc_other_user_data2/makedict/bitwarden.json create mode 100644 tests/structures/5_secret_calc_other_user_data/00-base.yml create mode 100644 tests/structures/5_secret_calc_other_user_data2/00-base.yml diff --git a/locale/rougail_user_data_bitwarden.pot b/locale/rougail_user_data_bitwarden.pot index b8f39f5..f9dc227 100644 --- a/locale/rougail_user_data_bitwarden.pot +++ b/locale/rougail_user_data_bitwarden.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2025-05-12 08:39+0200\n" +"POT-Creation-Date: 2025-10-05 21:30+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -35,43 +35,35 @@ msgstr "" msgid "cannot find Bitwarden command {0} please install it" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:175 -msgid "the value for \"{0}\" at index {1} is already set while it should be filled in by Bitwarden" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:181 -msgid "the value for \"{0}\" is already set while it should be filled in by Bitwarden" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:219 +#: src/rougail/user_data_bitwarden/data.py:202 msgid "the default value for \"{0}\" must be the Bitwarden item name" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:236 +#: src/rougail/user_data_bitwarden/data.py:225 msgid "cannot execute the \"{0}\" commandline from Bitwarden for \"{1}\": {2}" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:243 +#: src/rougail/user_data_bitwarden/data.py:234 msgid "item \"{0}\" in Bitwarden is not found for \"{1}\"" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:256 +#: src/rougail/user_data_bitwarden/data.py:249 msgid "several items found with name \"{0}\" in Bitwarden for \"{1}\": \"{2}\"" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:271 +#: src/rougail/user_data_bitwarden/data.py:268 msgid "unexpected datas \"{0}\" from Bitwarden for \"{1}\": {2}" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:279 +#: src/rougail/user_data_bitwarden/data.py:276 msgid "password" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:281 +#: src/rougail/user_data_bitwarden/data.py:278 msgid "username" msgstr "" -#: src/rougail/user_data_bitwarden/data.py:283 +#: src/rougail/user_data_bitwarden/data.py:280 msgid "item \"{0}\" in Bitwarden has no {1} for \"{2}\"" msgstr "" diff --git a/src/rougail/user_data_bitwarden/data.py b/src/rougail/user_data_bitwarden/data.py index 3b8f0d8..1fc84ed 100644 --- a/src/rougail/user_data_bitwarden/data.py +++ b/src/rougail/user_data_bitwarden/data.py @@ -30,7 +30,6 @@ from .i18n import _ class RougailUserDataBitwarden: - force_apply_user_data = True def __init__( self, @@ -112,176 +111,186 @@ class RougailUserDataBitwarden: return False def run(self): - self.set_passwords(self.config.forcepermissive) - return { - "errors": self.errors, - "warnings": self.warnings, - } + values = {} + self.set_passwords(self.config.forcepermissive, values) + return [ + { + "source": 'Bitwarden', + "errors": self.errors, + "warnings": self.warnings, + "values": values, + "options": { + "secret_manager": True, + } + } + ] - def run_commandline(self, cmd) -> str: - cpe = run(cmd, capture_output=True) - err = cpe.stderr.decode("utf8") - if cpe.returncode != 0 or err: - raise Exception("{0} ({1})".format(err, cpe.returncode)) - return cpe.stdout.decode("utf8") + def set_passwords(self, optiondescription, values): + for option in optiondescription.list(uncalculated=True): + if option.isoptiondescription(): + self.set_passwords(option, values) + elif option.information.get("bitwarden", False): + values[option.path()] = (set_password, self.leader_informations, self.bitwarden_command_line) - def get_key_from_commandline( - self, key_bitwarden: str, allow_multiple: bool - ) -> list[str]: - if self.bitwarden_command_line == "rbw": - keys = [] - items = self.run_commandline(["rbw", "search", key_bitwarden]).strip() - if items: - items = items.split("\n") - else: - items = [] - for item in items: - # if item.count('@') != 1: - # continue - if "@" in item: - keys.append(item.split("@", 1)[-1]) - else: - keys.append(item.rsplit("/", 1)[-1]) - if not allow_multiple: - if not items: - return [] - if len(items) > 1: - return [{"name": key} for key in keys] - keys = [key_bitwarden] - datas = [] - for key in keys: - data = loads( - self.run_commandline( - ["rbw", "get", key, "--raw", "--ignorecase"] - ).strip() - ) - datas.append({"name": key, "login": data["data"]}) - return datas - return loads( - self.run_commandline( - ["bw", "list", "items", "--search", key_bitwarden, "--nointeraction"] + +def set_password(leader_informations, bitwarden_command_line, *, option, warnings, errors): + path = option.path() + leader_key = None + if option.isfollower(): + leader_path = option.parent().leader().path() + if leader_path in leader_informations: + leader_key = leader_informations[leader_path][option.index()] + if not option.isleader(): + return get_values(bitwarden_command_line, option, warnings, errors, leader_key=leader_key) + leader_informations[path], option_values = get_values( + bitwarden_command_line, option, warnings, errors, multiple=True, leader_key=option.value.default()[0] + ) + return option_values + + +def get_values(bitwarden_command_line, option, warnings, errors, *, multiple=False, leader_key=None): + if leader_key: + key = leader_key + else: + key = option.value.default() + path = option.path() + type_ = option.information.get("type") + # FIXME retrait du permissive suffit ? + if "validator" not in option.property.get(): + option.property.add("validator") + if not isinstance(key, str): + errors.append( + _('the default value for "{0}" must be the Bitwarden item name').format( + path ) ) - - def set_passwords(self, optiondescription): - for option in optiondescription: - if option.isoptiondescription(): - self.set_passwords(option) - elif option.information.get("bitwarden", False): - path = option.path() - if not option.owner.isdefault(): - if option.isfollower(): - self.errors.append( - _( - 'the value for "{0}" at index {1} is already set while it should be filled in by Bitwarden' - ).format(path, option.index()) - ) - else: - self.errors.append( - _( - 'the value for "{0}" is already set while it should be filled in by Bitwarden' - ).format(path) - ) - continue - type_ = option.information.get("type") - if option.isleader(): - leader_values = [] - self.leader_informations[path] = [] - values = option.value.get() - for val in values: - names, values = self.get_values( - path, type_, val, allow_multiple=True - ) - if isinstance(values, list): - leader_values.extend(values) - self.leader_informations[path].extend(names) - else: - leader_values.append(values) - self.leader_informations[path].append(names) - option.value.set(leader_values) - else: - if option.isfollower(): - leader_path = optiondescription.leader().path() - if leader_path in self.leader_informations: - key_bitwarden = self.leader_informations[leader_path][ - option.index() - ] - else: - key_bitwarden = option.value.get() - else: - key_bitwarden = option.value.get() - option.value.set(self.get_values(path, type_, key_bitwarden)[1]) - option.permissive.add("novalidator") - - def get_values(self, path, type_, key_bitwarden, *, allow_multiple=False): - if not isinstance(key_bitwarden, str): - self.errors.append( - _('the default value for "{0}" must be the Bitwarden item name').format( - path - ) - ) - return None, None - if "ROUGAIL_BITWARDEN_MOCK_ENABLE" in environ: - if type_ == "secret": - value = "Ex4mpL3_P4ssw0rD" - else: - value = "example_login" - if allow_multiple: - return [key_bitwarden], [value] - return key_bitwarden, value - try: - data = self.get_key_from_commandline(key_bitwarden, allow_multiple) - except Exception as exc: - self.errors.append( - _( - 'cannot execute the "{0}" commandline from Bitwarden for "{1}": {2}' - ).format(self.bitwarden_command_line, path, exc) - ) - return None, None - if not data: - self.errors.append( - _('item "{0}" in Bitwarden is not found for "{1}"').format( - key_bitwarden, path - ) - ) - return None, None - if len(data) != 1: - names = [d["name"] for d in data] - if allow_multiple: - ret = [] - return names, [ - self.get_value(key_bitwarden, path, type_, d) for d in data - ] - self.errors.append( - _( - 'several items found with name "{0}" in Bitwarden for "{1}": "{2}"' - ).format(key_bitwarden, path, '", "'.join(names)) - ) - return None, None - return data[0]["name"], self.get_value(key_bitwarden, path, type_, data[0]) - - def get_value(self, key_bitwarden: str, path: str, type_: str, data: dict) -> str: - try: - if type_ == "secret": - value = data["login"]["password"] - else: - value = data["login"]["username"] - except Exception as exc: - self.errors.append( - _('unexpected datas "{0}" from Bitwarden for "{1}": {2}').format( - key_bitwarden, path, exc - ) - ) - value = None + if multiple: + return [], [] + return None + if "ROUGAIL_BITWARDEN_MOCK_ENABLE" in environ: + if type_ == "secret": + value = "Ex4mpL3_P4ssw0rD" else: - if value is None: - if type_ == "secret": - bw_type = _("password") - else: - bw_type = _("username") - self.errors.append( - _('item "{0}" in Bitwarden has no {1} for "{2}"').format( - key_bitwarden, bw_type, path - ) - ) + value = "example_login" + if multiple: + return [key], [value] return value + try: + if bitwarden_command_line == "rbw": + data = get_key_from_rbw(key, multiple) + else: + data = get_key_from_bw(key) + + except Exception as exc: + errors.append( + _( + 'cannot execute the "{0}" commandline from Bitwarden for "{1}": {2}' + ).format(bitwarden_command_line, path, exc) + ) + if multiple: + return [], [] + return None + if not data: + errors.append( + _('item "{0}" in Bitwarden is not found for "{1}"').format( + key, path + ) + ) + if multiple: + return [], [] + return None + if len(data) != 1: + names = [d["name"] for d in data] + if multiple: + ret = [] + return names, [ + get_value(key, path, type_, d, errors) for d in data + ] + errors.append( + _( + 'several items found with name "{0}" in Bitwarden for "{1}": "{2}"' + ).format(key, path, '", "'.join(names)) + ) + return None + value = get_value(key, path, type_, data[0], errors) + if multiple: + return [data[0]["name"]], [value] + return value + + +def get_value( key_bitwarden: str, path: str, type_: str, data: dict, errors: dict) -> str: + try: + if type_ == "secret": + value = data["login"]["password"] + else: + value = data["login"]["username"] + except Exception as exc: + errors.append( + _('unexpected datas "{0}" from Bitwarden for "{1}": {2}').format( + key_bitwarden, path, exc + ) + ) + value = None + else: + if value is None: + if type_ == "secret": + bw_type = _("password") + else: + bw_type = _("username") + errors.append( + _('item "{0}" in Bitwarden has no {1} for "{2}"').format( + key_bitwarden, bw_type, path + ) + ) + return value + + +def get_key_from_rbw( + key_bitwarden: str, multiple: bool + ): + keys = [] + items = run_commandline(["rbw", "search", key_bitwarden]).strip() + if items: + items = items.split("\n") + else: + items = [] + for item in items: + # if item.count('@') != 1: + # continue + if "@" in item: + keys.append(item.split("@", 1)[-1]) + else: + keys.append(item.rsplit("/", 1)[-1]) + if not multiple: + if not items: + return [] + if len(items) > 1: + return [{"name": key} for key in keys] + keys = [key_bitwarden] + datas = [] + for key in keys: + data = loads( + run_commandline( + ["rbw", "get", key, "--raw", "--ignorecase"] + ).strip() + ) + datas.append({"name": key, "login": data["data"]}) + return datas + + +def get_key_from_bw( + key_bitwarden: str, + ): + return loads( + run_commandline( + ["bw", "list", "items", "--search", key_bitwarden, "--nointeraction"] + ) + ) + + +def run_commandline(cmd) -> str: + cpe = run(cmd, capture_output=True) + err = cpe.stderr.decode("utf8") + if cpe.returncode != 0 or err: + raise Exception("{0} ({1})".format(err, cpe.returncode)) + return cpe.stdout.decode("utf8") diff --git a/tests/results/5_secret_calc_other_user_data/errors/bitwarden.json b/tests/results/5_secret_calc_other_user_data/errors/bitwarden.json new file mode 100644 index 0000000..5bf470f --- /dev/null +++ b/tests/results/5_secret_calc_other_user_data/errors/bitwarden.json @@ -0,0 +1,6 @@ +{ + "errors": [], + "warnings": [ + "variable or family \"rougail.modified_variable_single\" does not exist, it will be ignored when loading from By Hand" + ] +} \ No newline at end of file diff --git a/tests/results/5_secret_calc_other_user_data/makedict/bitwarden.json b/tests/results/5_secret_calc_other_user_data/makedict/bitwarden.json new file mode 100644 index 0000000..3c7a663 --- /dev/null +++ b/tests/results/5_secret_calc_other_user_data/makedict/bitwarden.json @@ -0,0 +1,10 @@ +{ + "rougail.host": "test", + "rougail.project": "5_secret_calc", + "rougail.environment": "environment", + "rougail.service": "service", + "rougail.modified_variable": ["user_1", "user_2"], + "rougail.dyn_user_1.secret": "bitwarden_password", + "rougail.dyn_user_2.secret": "bitwarden_password_2" + +} diff --git a/tests/results/5_secret_calc_other_user_data2/errors/bitwarden.json b/tests/results/5_secret_calc_other_user_data2/errors/bitwarden.json new file mode 100644 index 0000000..d2082d6 --- /dev/null +++ b/tests/results/5_secret_calc_other_user_data2/errors/bitwarden.json @@ -0,0 +1,6 @@ +{ + "errors": [], + "warnings": [ + "variable or family \"rougail.modified_variable\" does not exist, it will be ignored when loading from By Hand" + ] +} \ No newline at end of file diff --git a/tests/results/5_secret_calc_other_user_data2/makedict/bitwarden.json b/tests/results/5_secret_calc_other_user_data2/makedict/bitwarden.json new file mode 100644 index 0000000..baa35d9 --- /dev/null +++ b/tests/results/5_secret_calc_other_user_data2/makedict/bitwarden.json @@ -0,0 +1,8 @@ +{ + "rougail.host": "test", + "rougail.project": "5_secret_calc", + "rougail.environment": "environment", + "rougail.service": "service", + "rougail.modified_variable_single": "user_2", + "rougail.secret": "bitwarden_password_2" +} \ No newline at end of file diff --git a/tests/structures/5_secret_calc_other_user_data/00-base.yml b/tests/structures/5_secret_calc_other_user_data/00-base.yml new file mode 100644 index 0000000..d99d853 --- /dev/null +++ b/tests/structures/5_secret_calc_other_user_data/00-base.yml @@ -0,0 +1,39 @@ +--- +version: 1.1 + +host: + description: hostname + default: test + +project: + description: the project + default: 5_secret_calc + +environment: + description: the environment + default: environment + +service: + description: the service + default: service + +modified_variable: [] # a variable modified + +dyn_{{ identifier }}: + dynamic: + variable: _.modified_variable + + secret: + description: the second secret + type: secret + secret_manager: + host: + variable: __.host + project: + variable: __.project + environment: + variable: __.environment + service: + variable: __.service + user: + type: identifier diff --git a/tests/structures/5_secret_calc_other_user_data2/00-base.yml b/tests/structures/5_secret_calc_other_user_data2/00-base.yml new file mode 100644 index 0000000..1039e4e --- /dev/null +++ b/tests/structures/5_secret_calc_other_user_data2/00-base.yml @@ -0,0 +1,35 @@ +--- +version: 1.1 + +host: + description: hostname + default: test + +project: + description: the project + default: 5_secret_calc + +environment: + description: the environment + default: environment + +service: + description: the service + default: service + +modified_variable_single: # a variable modified + +secret: + description: the second secret + type: secret + secret_manager: + host: + variable: _.host + project: + variable: _.project + environment: + variable: _.environment + service: + variable: _.service + user: + variable: _.modified_variable_single diff --git a/tests/test_load.py b/tests/test_load.py index c293eaa..0466af1 100644 --- a/tests/test_load.py +++ b/tests/test_load.py @@ -16,16 +16,19 @@ from rougail_tests.utils import config_to_dict test_dir = Path(__file__).parent / 'structures' -def _test_dictionaries(test_dir, command, env=False): +def _test_structural_files(test_dir, command, *, env=False, modified=False): rougailconfig = RougailConfig.copy() - rougailconfig['main_dictionaries'] = [str(test_dir)] + rougailconfig['main_structural_directories'] = [str(test_dir)] # rougailconfig['tiramisu_cache'] = "cache.py" rougailconfig['step.user_data'] = ['bitwarden'] rougailconfig['bitwarden.command'] = command rougail = Rougail(rougailconfig) config = rougail.run() # loads variables in the tiramisu config - errors = RougailUserData(config, rougailconfig=rougailconfig).run() + generated_user_data = RougailUserData(config, rougailconfig=rougailconfig).run() + if modified: + generated_user_data.insert(0, {'source': 'By Hand', 'errors': [], 'warnings': [], 'values': {'rougail.modified_variable': ['user_1', 'user_2'], 'rougail.modified_variable_single': 'user_2'}}) + errors = rougail.user_datas(generated_user_data) #expected output config_dict = dict(config_to_dict(config.forcepermissive.value.get())) if not env: @@ -50,322 +53,328 @@ def _test_dictionaries(test_dir, command, env=False): dump(errors, json_file, indent=4) with open(errors_file) as json_file: expected_errors = load(json_file) - # expected_errors = { - # 'errors': [], - # 'warnings': [], - # } - assert expected_errors == errors + assert expected_errors == errors, errors_file # - assert expected == config_dict + assert expected == config_dict, ok_file -def test_dictionaries_1_secret_rbw(): +def test_structural_files_1_secret_rbw(): "tests the output" - _test_dictionaries(test_dir / '1_secret', 'rbw') + _test_structural_files(test_dir / '1_secret', 'rbw') -def test_dictionaries_1_secret_bw(): +def test_structural_files_1_secret_bw(): "tests the output" - _test_dictionaries(test_dir / '1_secret', 'bw') + _test_structural_files(test_dir / '1_secret', 'bw') -def test_dictionaries_1_secret_unknown_rbw(): +def test_structural_files_1_secret_unknown_rbw(): "tests the output" - _test_dictionaries(test_dir / '1_secret_unknown', 'rbw') + _test_structural_files(test_dir / '1_secret_unknown', 'rbw') -def test_dictionaries_1_secret_unknown_bw(): +def test_structural_files_1_secret_unknown_bw(): "tests the output" - _test_dictionaries(test_dir / '1_secret_unknown', 'bw') + _test_structural_files(test_dir / '1_secret_unknown', 'bw') -def test_dictionaries_2_username_secret_rbw(): +def test_structural_files_2_username_secret_rbw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret', 'rbw') + _test_structural_files(test_dir / '2_username_secret', 'rbw') -def test_dictionaries_2_username_secret_bw(): +def test_structural_files_2_username_secret_bw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret', 'bw') + _test_structural_files(test_dir / '2_username_secret', 'bw') -def test_dictionaries_2_username_secret_upper_rbw(): +def test_structural_files_2_username_secret_upper_rbw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret_upper', 'rbw') + _test_structural_files(test_dir / '2_username_secret_upper', 'rbw') -def test_dictionaries_2_username_secret_upper_bw(): +def test_structural_files_2_username_secret_upper_bw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret_upper', 'bw') + _test_structural_files(test_dir / '2_username_secret_upper', 'bw') -def test_dictionaries_2_username_secret_invalid_rbw(): +def test_structural_files_2_username_secret_invalid_rbw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret_invalid', 'rbw') + _test_structural_files(test_dir / '2_username_secret_invalid', 'rbw') -def test_dictionaries_2_username_secret_invalid_bw(): +def test_structural_files_2_username_secret_invalid_bw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret_invalid', 'bw') + _test_structural_files(test_dir / '2_username_secret_invalid', 'bw') -def test_dictionaries_2_username_secret_hidden_rbw(): +def test_structural_files_2_username_secret_hidden_rbw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret_hidden', 'rbw') + _test_structural_files(test_dir / '2_username_secret_hidden', 'rbw') -def test_dictionaries_2_username_secret_hidden_bw(): +def test_structural_files_2_username_secret_hidden_bw(): "tests the output" - _test_dictionaries(test_dir / '2_username_secret_hidden', 'bw') + _test_structural_files(test_dir / '2_username_secret_hidden', 'bw') -def test_dictionaries_3_leadership_secret_rbw(): +def test_structural_files_3_leadership_secret_rbw(): "tests the output" - _test_dictionaries(test_dir / '3_leadership_secret', 'rbw') + _test_structural_files(test_dir / '3_leadership_secret', 'rbw') -def test_dictionaries_3_leadership_secret_bw(): +def test_structural_files_3_leadership_secret_bw(): "tests the output" - _test_dictionaries(test_dir / '3_leadership_secret', 'bw') + _test_structural_files(test_dir / '3_leadership_secret', 'bw') -def test_dictionaries_3_leadership_secret_several_rbw(): +def test_structural_files_3_leadership_secret_several_rbw(): "tests the output" - _test_dictionaries(test_dir / '3_leadership_secret_several', 'rbw') + _test_structural_files(test_dir / '3_leadership_secret_several', 'rbw') -def test_dictionaries_3_leadership_secret_several_bw(): +def test_structural_files_3_leadership_secret_several_bw(): "tests the output" - _test_dictionaries(test_dir / '3_leadership_secret_several', 'bw') + _test_structural_files(test_dir / '3_leadership_secret_several', 'bw') -def test_dictionaries_4_several_secrets_rbw(): +def test_structural_files_4_several_secrets_rbw(): "tests the output" - _test_dictionaries(test_dir / '4_several_secrets', 'rbw') + _test_structural_files(test_dir / '4_several_secrets', 'rbw') -def test_dictionaries_4_several_secrets_bw(): +def test_structural_files_4_several_secrets_bw(): "tests the output" - _test_dictionaries(test_dir / '4_several_secrets', 'bw') + _test_structural_files(test_dir / '4_several_secrets', 'bw') -def test_dictionaries_4_several_secrets_upper_rbw(): +def test_structural_files_4_several_secrets_upper_rbw(): "tests the output" - _test_dictionaries(test_dir / '4_several_secrets_upper', 'rbw') + _test_structural_files(test_dir / '4_several_secrets_upper', 'rbw') -def test_dictionaries_4_several_secrets_upper_bw(): +def test_structural_files_4_several_secrets_upper_bw(): "tests the output" - _test_dictionaries(test_dir / '4_several_secrets_upper', 'bw') + _test_structural_files(test_dir / '4_several_secrets_upper', 'bw') -def test_dictionaries_5_secret_calc_rbw(): +def test_structural_files_5_secret_calc_rbw(): "tests the output" - _test_dictionaries(test_dir / '5_secret_calc', 'rbw') + _test_structural_files(test_dir / '5_secret_calc', 'rbw') -def test_dictionaries_5_secret_calc_bw(): +def test_structural_files_5_secret_calc_bw(): "tests the output" - _test_dictionaries(test_dir / '5_secret_calc', 'bw') + _test_structural_files(test_dir / '5_secret_calc', 'bw') -def test_dictionaries_6_no_username_rbw(): +def test_structural_files_5_secret_calc_other_user_data_rbw(): "tests the output" - _test_dictionaries(test_dir / '6_no_username', 'rbw') + _test_structural_files(test_dir / '5_secret_calc_other_user_data', 'rbw', modified=True) -def test_dictionaries_6_no_username_bw(): +def test_structural_files_5_secret_calc_other_user_data2_rbw(): "tests the output" - _test_dictionaries(test_dir / '6_no_username', 'bw') + _test_structural_files(test_dir / '5_secret_calc_other_user_data2', 'rbw', modified=True) -def test_dictionaries_8_multi_variable_rbw(): +def test_structural_files_6_no_username_rbw(): + "tests the output" + _test_structural_files(test_dir / '6_no_username', 'rbw') + + +def test_structural_files_6_no_username_bw(): + "tests the output" + _test_structural_files(test_dir / '6_no_username', 'bw') + + +def test_structural_files_8_multi_variable_rbw(): "tests the output" with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '8_multi_variable', 'rbw') + _test_structural_files(test_dir / '8_multi_variable', 'rbw') assert err.value.errno == 57 -def test_dictionaries_8_multi_variable_bw(): +def test_structural_files_8_multi_variable_bw(): "tests the output" with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '8_multi_variable', 'bw') + _test_structural_files(test_dir / '8_multi_variable', 'bw') assert err.value.errno == 57 -def test_dictionaries_9_unknown_type_rbw(): +def test_structural_files_9_unknown_type_rbw(): "tests the output" with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '9_unknown_type', 'rbw') + _test_structural_files(test_dir / '9_unknown_type', 'rbw') assert err.value.errno == 56 -def test_dictionaries_9_unknown_type_bw(): +def test_structural_files_9_unknown_type_bw(): "tests the output" with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '9_unknown_type', 'bw') + _test_structural_files(test_dir / '9_unknown_type', 'bw') assert err.value.errno == 56 -def test_dictionaries_env_1_secret_rbw(): +def test_structural_files_env_1_secret_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '1_secret', 'rbw', True) + _test_structural_files(test_dir / '1_secret', 'rbw', env=True) -def test_dictionaries_env_1_secret_bw(): +def test_structural_files_env_1_secret_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '1_secret', 'bw', True) + _test_structural_files(test_dir / '1_secret', 'bw', env=True) -def test_dictionaries_env_1_secret_unknown_rbw(): +def test_structural_files_env_1_secret_unknown_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '1_secret_unknown', 'rbw', True) + _test_structural_files(test_dir / '1_secret_unknown', 'rbw', env=True) -def test_dictionaries_env_1_secret_unknown_bw(): +def test_structural_files_env_1_secret_unknown_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '1_secret_unknown', 'bw', True) + _test_structural_files(test_dir / '1_secret_unknown', 'bw', env=True) -def test_dictionaries_env_2_username_secret_rbw(): +def test_structural_files_env_2_username_secret_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret', 'rbw', True) + _test_structural_files(test_dir / '2_username_secret', 'rbw', env=True) -def test_dictionaries_env_2_username_secret_bw(): +def test_structural_files_env_2_username_secret_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret', 'bw', True) + _test_structural_files(test_dir / '2_username_secret', 'bw', env=True) -def test_dictionaries_env_2_username_secret_upper_rbw(): +def test_structural_files_env_2_username_secret_upper_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret_upper', 'rbw', True) + _test_structural_files(test_dir / '2_username_secret_upper', 'rbw', env=True) -def test_dictionaries_env_2_username_secret_upper_bw(): +def test_structural_files_env_2_username_secret_upper_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret_upper', 'bw', True) + _test_structural_files(test_dir / '2_username_secret_upper', 'bw', env=True) -def test_dictionaries_env_2_username_secret_invalid_rbw(): +def test_structural_files_env_2_username_secret_invalid_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret_invalid', 'rbw', True) + _test_structural_files(test_dir / '2_username_secret_invalid', 'rbw', env=True) -def test_dictionaries_env_2_username_secret_invalid_bw(): +def test_structural_files_env_2_username_secret_invalid_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret_invalid', 'bw', True) + _test_structural_files(test_dir / '2_username_secret_invalid', 'bw', env=True) -def test_dictionaries_env_2_username_secret_hidden_rbw(): +def test_structural_files_env_2_username_secret_hidden_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret_hidden', 'rbw', True) + _test_structural_files(test_dir / '2_username_secret_hidden', 'rbw', env=True) -def test_dictionaries_env_2_username_secret_hidden_bw(): +def test_structural_files_env_2_username_secret_hidden_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '2_username_secret_hidden', 'bw', True) + _test_structural_files(test_dir / '2_username_secret_hidden', 'bw', env=True) -def test_dictionaries_env_3_leadership_secret_rbw(): +def test_structural_files_env_3_leadership_secret_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '3_leadership_secret', 'rbw', True) + _test_structural_files(test_dir / '3_leadership_secret', 'rbw', env=True) -def test_dictionaries_env_3_leadership_secret_bw(): +def test_structural_files_env_3_leadership_secret_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '3_leadership_secret', 'bw', True) + _test_structural_files(test_dir / '3_leadership_secret', 'bw', env=True) -def test_dictionaries_env_3_leadership_secret_several_rbw(): +def test_structural_files_env_3_leadership_secret_several_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '3_leadership_secret_several', 'rbw', True) + _test_structural_files(test_dir / '3_leadership_secret_several', 'rbw', env=True) -def test_dictionaries_env_3_leadership_secret_several_bw(): +def test_structural_files_env_3_leadership_secret_several_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '3_leadership_secret_several', 'bw', True) + _test_structural_files(test_dir / '3_leadership_secret_several', 'bw', env=True) -def test_dictionaries_env_4_several_secrets_rbw(): +def test_structural_files_env_4_several_secrets_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '4_several_secrets', 'rbw', True) + _test_structural_files(test_dir / '4_several_secrets', 'rbw', env=True) -def test_dictionaries_env_4_several_secrets_bw(): +def test_structural_files_env_4_several_secrets_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '4_several_secrets', 'bw', True) + _test_structural_files(test_dir / '4_several_secrets', 'bw', env=True) -def test_dictionaries_env_4_several_secrets_upper_rbw(): +def test_structural_files_env_4_several_secrets_upper_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '4_several_secrets_upper', 'rbw', True) + _test_structural_files(test_dir / '4_several_secrets_upper', 'rbw', env=True) -def test_dictionaries_env_4_several_secrets_upper_bw(): +def test_structural_files_env_4_several_secrets_upper_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '4_several_secrets_upper', 'bw', True) + _test_structural_files(test_dir / '4_several_secrets_upper', 'bw', env=True) -def test_dictionaries_env_5_secret_calc_rbw(): +def test_structural_files_env_5_secret_calc_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '5_secret_calc', 'rbw', True) + _test_structural_files(test_dir / '5_secret_calc', 'rbw', env=True) -def test_dictionaries_env_5_secret_calc_bw(): +def test_structural_files_env_5_secret_calc_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): - _test_dictionaries(test_dir / '5_secret_calc', 'bw', True) + _test_structural_files(test_dir / '5_secret_calc', 'bw', env=True) -def test_dictionaries_env_8_multi_variable_rbw(): +def test_structural_files_env_8_multi_variable_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '8_multi_variable', 'rbw', True) + _test_structural_files(test_dir / '8_multi_variable', 'rbw', env=True) assert err.value.errno == 57 -def test_dictionaries_env_8_multi_variable_bw(): +def test_structural_files_env_8_multi_variable_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '8_multi_variable', 'bw', True) + _test_structural_files(test_dir / '8_multi_variable', 'bw', env=True) assert err.value.errno == 57 -def test_dictionaries_env_9_unknown_type_rbw(): +def test_structural_files_env_9_unknown_type_rbw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '9_unknown_type', 'rbw', True) + _test_structural_files(test_dir / '9_unknown_type', 'rbw', env=True) assert err.value.errno == 56 -def test_dictionaries_env_9_unknown_type_bw(): +def test_structural_files_env_9_unknown_type_bw(): "tests the output" with mock.patch.dict(os.environ, {'ROUGAIL_BITWARDEN_MOCK_ENABLE': '1'}): with raises(DictConsistencyError) as err: - _test_dictionaries(test_dir / '9_unknown_type', 'bw', True) + _test_structural_files(test_dir / '9_unknown_type', 'bw', env=True) assert err.value.errno == 56