diff --git a/src/rougail/convert/convert.py b/src/rougail/convert/convert.py index af33deb84..ef9439401 100644 --- a/src/rougail/convert/convert.py +++ b/src/rougail/convert/convert.py @@ -697,7 +697,7 @@ class ParserVariable: family_is_dynamic, ) self.parse_params(path, obj, sources) - self.parse_secret_manager(path, obj, sources, family_is_dynamic) + self.parse_secret_manager(path, obj, sources, family_is_dynamic, copy_before_set) exists = obj.pop("exists", None) redefine = obj.pop("redefine", False) or force_redefine is True if not redefine and not exists: @@ -843,11 +843,14 @@ class ParserVariable: ) from err obj["params"] = params - def parse_secret_manager(self, path, obj, sources, family_is_dynamic): + def parse_secret_manager(self, path, obj, sources, family_is_dynamic, copy_before_set): """Parse variable secret_manager""" if "secret_manager" not in obj: return if not isinstance(obj["secret_manager"], dict): + if copy_before_set: + obj["secret_manager"] = obj["secret_manager"].copy() + return raise DictConsistencyError( _("secret_manager must be a dict for {0}").format(path), 64, diff --git a/src/rougail/types.py b/src/rougail/types.py index 386f026ac..efa466dd9 100644 --- a/src/rougail/types.py +++ b/src/rougail/types.py @@ -17,17 +17,21 @@ along with this program. If not, see . """ from .config import StaticRougailConvert from .i18n import _ +from .error import DictConsistencyError class TypeRougailConvert(StaticRougailConvert): def __init__( self, main_structural_directories: list[str], + secret_pattern: str, ) -> None: super().__init__(False, {"sort_structural_files_all": True, "main_namespace": None, "main_structural_directories": main_structural_directories, }) + self.secret_pattern = secret_pattern + def load_config(self) -> None: super().load_config() @@ -40,7 +44,7 @@ def rougail_type(rougailconfig): types = rougailconfig["types"] if not types: return {}, {} - convert = TypeRougailConvert(types) + convert = TypeRougailConvert(types, rougailconfig["secret_manager.pattern"]) convert.init() convert.parse_directories() return ({typ: to_dict_variable(convert.paths[typ]) for typ in convert.variables}, @@ -63,9 +67,7 @@ def to_dict_family(family_name, paths, parents, families, root=True): variable_name = variable.name if variable_path in families: if variable.type == "leadership": - raise DictConsistencyError(_("type is not compatible with leadership family"), variable.xmlfiles) - if variable.type == "dynamic": - raise DictConsistencyError(_("type is not compatible with dynamic family"), variable.xmlfiles) + raise DictConsistencyError(_("type is not compatible with leadership family"), 86, variable.xmlfiles) if variable_name in ret: ret["_" + variable_name] = ret.pop(variable_name) ret[variable_name] = to_dict_family(variable.path, paths, parents, families, False) diff --git a/src/rougail/user_data.py b/src/rougail/user_data.py index 483b79893..d35d50955 100644 --- a/src/rougail/user_data.py +++ b/src/rougail/user_data.py @@ -472,22 +472,23 @@ class UserData: ): option._subconfig} ) else: - if self.unknown_user_data_error: - msg = _( - "family {0} has property {1}, so cannot access to {2}, it has been loading from {3}" + if not options.get("options", {}).get("secret_manager", False): + if self.unknown_user_data_error: + msg = _( + "family {0} has property {1}, so cannot access to {2}, it has been loading from {3}" + ) + else: + msg = _( + "family {0} has property {1}, so cannot access to {2}, it will be ignored when loading from {3}" + ) + self.unknowns.append({ + msg.format( + err_description, + properties, + display_name, + options["source"], + ): option._subconfig} ) - else: - msg = _( - "family {0} has property {1}, so cannot access to {2}, it will be ignored when loading from {3}" - ) - self.unknowns.append({ - msg.format( - err_description, - properties, - display_name, - options["source"], - ): option._subconfig} - ) else: if self.unknown_user_data_error: msg = _( diff --git a/tests/test_types.py b/tests/test_types.py index 47def1a95..538933a84 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -77,3 +77,7 @@ def test_type_family_subfamily(): def test_type_variable_hidden(): type_variable("variable_hidden") + + +def test_type_dynfamily(): + type_variable("family_dynfamily") diff --git a/tests/types/result/family_dynfamily/tiramisu.py b/tests/types/result/family_dynfamily/tiramisu.py new file mode 100644 index 000000000..bf7816d31 --- /dev/null +++ b/tests/types/result/family_dynfamily/tiramisu.py @@ -0,0 +1,28 @@ +from tiramisu import * +from tiramisu.setting import ALLOWED_LEADER_PROPERTIES +from re import compile as re_compile +from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription +try: + groups.namespace +except: + groups.addgroup('namespace') +ALLOWED_LEADER_PROPERTIES.add("basic") +ALLOWED_LEADER_PROPERTIES.add("standard") +ALLOWED_LEADER_PROPERTIES.add("advanced") +option_3 = StrOption(name="a_first_variable", doc="a first variable", default="a modified value", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml'], 'type': 'string'}) +option_5 = StrOption(name="identifier", doc="identifier", multi=True, default=["family"], default_multi="family", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml'], 'type': 'string'}) +option_6 = StrOption(name="a_second_variable", doc="a second variable", default="a modified value", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml'], 'type': 'string'}) +optiondescription_4 = OptionDescription(name="a_sub_{{ identifier }}", doc="My sub{{ identifier }}", children=[option_5, option_6], properties=frozenset({"standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml']}) +optiondescription_2 = OptionDescription(name="my_family_1", doc="My family type", children=[option_3, optiondescription_4], properties=frozenset({"standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml']}) +option_8 = StrOption(name="a_first_variable", doc="a first variable", default="a value", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml'], 'type': 'string'}) +option_10 = StrOption(name="identifier", doc="identifier", multi=True, default=["family"], default_multi="family", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml'], 'type': 'string'}) +option_11 = StrOption(name="a_second_variable", doc="a second variable", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml'], 'type': 'string'}) +optiondescription_9 = OptionDescription(name="a_sub_{{ identifier }}", doc="My sub{{ identifier }}", children=[option_10, option_11], properties=frozenset({"basic"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml']}) +optiondescription_7 = OptionDescription(name="my_family_2", doc="My family type", children=[option_8, optiondescription_9], properties=frozenset({"basic"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml']}) +option_13 = StrOption(name="a_first_variable", doc="a first variable", default="a value", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml'], 'type': 'string'}) +option_15 = StrOption(name="identifier", doc="identifier", multi=True, default=["family"], default_multi="family", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml'], 'type': 'string'}) +option_16 = StrOption(name="a_second_variable", doc="a second variable", default="a modified value 2", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml'], 'type': 'string'}) +optiondescription_14 = OptionDescription(name="a_sub_{{ identifier }}", doc="My sub{{ identifier }}", children=[option_15, option_16], properties=frozenset({"standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml']}) +optiondescription_12 = OptionDescription(name="my_family_3", doc="My family type", children=[option_13, optiondescription_14], properties=frozenset({"standard"}), informations={'ymlfiles': ['tests/types/types/family_dynfamily/00_structure.yml', 'tests/types/structures/family_dynfamily/00_structure.yml']}) +optiondescription_1 = OptionDescription(name="rougail", doc="rougail", group_type=groups.namespace, children=[optiondescription_2, optiondescription_7, optiondescription_12], properties=frozenset({"basic"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1]) diff --git a/tests/types/result/family_dynfamily/variables.json b/tests/types/result/family_dynfamily/variables.json new file mode 100644 index 000000000..0d39928f1 --- /dev/null +++ b/tests/types/result/family_dynfamily/variables.json @@ -0,0 +1,17 @@ +{ + "rougail.my_family_1.a_first_variable": "a modified value", + "rougail.my_family_1.a_sub_{{\u00a0identifier }}.identifier": [ + "family" + ], + "rougail.my_family_1.a_sub_{{\u00a0identifier }}.a_second_variable": "a modified value", + "rougail.my_family_2.a_first_variable": "a value", + "rougail.my_family_2.a_sub_{{\u00a0identifier }}.identifier": [ + "family" + ], + "rougail.my_family_2.a_sub_{{\u00a0identifier }}.a_second_variable": null, + "rougail.my_family_3.a_first_variable": "a value", + "rougail.my_family_3.a_sub_{{\u00a0identifier }}.identifier": [ + "family" + ], + "rougail.my_family_3.a_sub_{{\u00a0identifier }}.a_second_variable": "a modified value 2" +} \ No newline at end of file diff --git a/tests/types/result/family_dynfamily/variables_rw.json b/tests/types/result/family_dynfamily/variables_rw.json new file mode 100644 index 000000000..0d39928f1 --- /dev/null +++ b/tests/types/result/family_dynfamily/variables_rw.json @@ -0,0 +1,17 @@ +{ + "rougail.my_family_1.a_first_variable": "a modified value", + "rougail.my_family_1.a_sub_{{\u00a0identifier }}.identifier": [ + "family" + ], + "rougail.my_family_1.a_sub_{{\u00a0identifier }}.a_second_variable": "a modified value", + "rougail.my_family_2.a_first_variable": "a value", + "rougail.my_family_2.a_sub_{{\u00a0identifier }}.identifier": [ + "family" + ], + "rougail.my_family_2.a_sub_{{\u00a0identifier }}.a_second_variable": null, + "rougail.my_family_3.a_first_variable": "a value", + "rougail.my_family_3.a_sub_{{\u00a0identifier }}.identifier": [ + "family" + ], + "rougail.my_family_3.a_sub_{{\u00a0identifier }}.a_second_variable": "a modified value 2" +} \ No newline at end of file diff --git a/tests/types/structures/family_dynfamily/00_structure.yml b/tests/types/structures/family_dynfamily/00_structure.yml new file mode 100644 index 000000000..2cc105af6 --- /dev/null +++ b/tests/types/structures/family_dynfamily/00_structure.yml @@ -0,0 +1,23 @@ +%YAML 1.2 +--- +version: 1.1 + +my_family_1: + type: my_family_type + + a_first_variable: a modified value + + a_sub_{{ identifier }}: + + a_second_variable: a modified value + +my_family_2: + type: my_family_type + +my_family_3: + type: my_family_type + + a_sub_{{ identifier }}: + + a_second_variable: a modified value 2 +... diff --git a/tests/types/types/family_dynfamily/00_structure.yml b/tests/types/types/family_dynfamily/00_structure.yml new file mode 100644 index 000000000..51293052a --- /dev/null +++ b/tests/types/types/family_dynfamily/00_structure.yml @@ -0,0 +1,14 @@ +%YAML 1.2 +--- +version: 1.1 + +my_family_type: # My family type + + a_first_variable: a value # a first variable + + a_sub_{{ identifier }}: # My sub{{ identifier }} + identifier: + - family + + a_second_variable: # a second variable +...