From 6af98ec1e43ab89fec4ef2f0e24690f2ffd6beda Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Fri, 27 Jan 2023 11:15:51 +0100 Subject: [PATCH] add unix_permissions option support and use it for mode --- src/rougail/annotator/variable.py | 1 + src/rougail/data/rougail.dtd | 4 +- src/rougail/data/rougail.yml | 8 ++++ src/rougail/template/base.py | 5 +++ src/rougail/template/systemd.py | 10 +++-- .../01base_file_mode2/__init__.py | 0 .../01base_file_mode2/makedict/after.json | 22 +++++++++ .../01base_file_mode2/makedict/base.json | 7 +++ .../01base_file_mode2/makedict/before.json | 22 +++++++++ .../01base_file_mode2/result/etc/file | 1 + .../result/tmpfiles.d/0rougail.conf | 1 + .../01base_file_mode2/tiramisu/base.py | 32 +++++++++++++ .../01base_file_mode2/tiramisu/multi.py | 45 +++++++++++++++++++ .../dictionaries/01base_file_mode2/tmpl/file | 1 + .../01base_file_mode2/xml/00-base.xml | 8 ++++ .../01base_file_mode2/yml/00-base.yml | 7 +++ tests/test_others.py | 4 +- 17 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 tests/dictionaries/01base_file_mode2/__init__.py create mode 100644 tests/dictionaries/01base_file_mode2/makedict/after.json create mode 100644 tests/dictionaries/01base_file_mode2/makedict/base.json create mode 100644 tests/dictionaries/01base_file_mode2/makedict/before.json create mode 100644 tests/dictionaries/01base_file_mode2/result/etc/file create mode 100644 tests/dictionaries/01base_file_mode2/result/tmpfiles.d/0rougail.conf create mode 100644 tests/dictionaries/01base_file_mode2/tiramisu/base.py create mode 100644 tests/dictionaries/01base_file_mode2/tiramisu/multi.py create mode 100644 tests/dictionaries/01base_file_mode2/tmpl/file create mode 100644 tests/dictionaries/01base_file_mode2/xml/00-base.xml create mode 100644 tests/dictionaries/01base_file_mode2/yml/00-base.yml diff --git a/src/rougail/annotator/variable.py b/src/rougail/annotator/variable.py index de629b13d..bfc83e3cd 100644 --- a/src/rougail/annotator/variable.py +++ b/src/rougail/annotator/variable.py @@ -63,6 +63,7 @@ CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int), 'mac': dict(opttype="MACOption"), 'cidr': dict(opttype="IPOption", initkwargs={'cidr': True}), 'network_cidr': dict(opttype="NetworkOption", initkwargs={'cidr': True}), + 'unix_permissions': dict(opttype="PermissionsOption", initkwargs={'warnings_only': True}, func=int), } diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd index 21706d226..86ca62208 100644 --- a/src/rougail/data/rougail.dtd +++ b/src/rougail/data/rougail.dtd @@ -71,7 +71,7 @@ - + @@ -111,7 +111,7 @@ - + diff --git a/src/rougail/data/rougail.yml b/src/rougail/data/rougail.yml index e60196eee..1fc2ab2aa 100644 --- a/src/rougail/data/rougail.yml +++ b/src/rougail/data/rougail.yml @@ -322,6 +322,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" family: type: seq sequence: @@ -467,6 +468,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" family: required: false type: seq @@ -613,6 +615,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" family: required: false name: @@ -787,6 +790,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" family: type: seq sequence: @@ -932,6 +936,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" family: required: false name: @@ -1092,6 +1097,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" family: type: seq sequence: @@ -1237,6 +1243,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" family: required: false name: @@ -1397,6 +1404,7 @@ mapping: - "cidr" - "network_cidr" - "choice" + - "unix_permissions" constraints: required: false type: seq diff --git a/src/rougail/template/base.py b/src/rougail/template/base.py index bb12cdaa9..9e9fb2145 100644 --- a/src/rougail/template/base.py +++ b/src/rougail/template/base.py @@ -587,6 +587,11 @@ class RougailBaseTemplate: ) -> None: # pragma: no cover raise NotImplementedError(_('cannot instanciate this service type override')) + def get_data_certificates(self, + *args, + ) -> None: # pragma: no cover + pass + async def _load_variables(self, optiondescription, is_variable_namespace: str, diff --git a/src/rougail/template/systemd.py b/src/rougail/template/systemd.py index c8060630c..cca10ae9a 100644 --- a/src/rougail/template/systemd.py +++ b/src/rougail/template/systemd.py @@ -56,10 +56,14 @@ class RougailSystemdTemplate(RougailBaseTemplate): tmp_local_dir = (f"%%filename.startswith('{local_dir}')" for local_dir in LOCAL_DIR) self.rougail_tmpl_template += '%if ' + ' or '.join(tmp_local_dir) self.rougail_tmpl_template += f""" -%if {self.rougailconfig['systemd_tmpfile_delete_before_create']} + %if {self.rougailconfig['systemd_tmpfile_delete_before_create']} r %%filename -%end if -C %%filename 0%%file.mode %%file.owner %%file.group - {self.rougailconfig['systemd_tmpfile_factory_dir']}%%filename + %end if +%set %%mode = %%str(%%file.mode) + %if %%len(%%mode) == 3 +%set %%mode = '0' + %%mode + %end if +C %%filename %%mode %%file.owner %%file.group - {self.rougailconfig['systemd_tmpfile_factory_dir']}%%filename %end if %end def %for %%service in %%services diff --git a/tests/dictionaries/01base_file_mode2/__init__.py b/tests/dictionaries/01base_file_mode2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/01base_file_mode2/makedict/after.json b/tests/dictionaries/01base_file_mode2/makedict/after.json new file mode 100644 index 000000000..05af219b0 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/makedict/after.json @@ -0,0 +1,22 @@ +{ + "services.test_service.files.file.name": { + "owner": "default", + "value": "/etc/file" + }, + "services.test_service.files.file.source": { + "owner": "default", + "value": "file" + }, + "services.test_service.files.file.activate": { + "owner": "default", + "value": true + }, + "services.test_service.activate": { + "owner": "default", + "value": true + }, + "services.test_service.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/01base_file_mode2/makedict/base.json b/tests/dictionaries/01base_file_mode2/makedict/base.json new file mode 100644 index 000000000..2296bda68 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/makedict/base.json @@ -0,0 +1,7 @@ +{ + "services.test_service.files.file.name": "/etc/file", + "services.test_service.files.file.source": "file", + "services.test_service.files.file.activate": true, + "services.test_service.activate": true, + "services.test_service.manage": true +} diff --git a/tests/dictionaries/01base_file_mode2/makedict/before.json b/tests/dictionaries/01base_file_mode2/makedict/before.json new file mode 100644 index 000000000..05af219b0 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/makedict/before.json @@ -0,0 +1,22 @@ +{ + "services.test_service.files.file.name": { + "owner": "default", + "value": "/etc/file" + }, + "services.test_service.files.file.source": { + "owner": "default", + "value": "file" + }, + "services.test_service.files.file.activate": { + "owner": "default", + "value": true + }, + "services.test_service.activate": { + "owner": "default", + "value": true + }, + "services.test_service.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/01base_file_mode2/result/etc/file b/tests/dictionaries/01base_file_mode2/result/etc/file new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/result/etc/file @@ -0,0 +1 @@ +test diff --git a/tests/dictionaries/01base_file_mode2/result/tmpfiles.d/0rougail.conf b/tests/dictionaries/01base_file_mode2/result/tmpfiles.d/0rougail.conf new file mode 100644 index 000000000..546319fa2 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/result/tmpfiles.d/0rougail.conf @@ -0,0 +1 @@ +C /etc/file 1755 root root - /usr/local/lib/etc/file diff --git a/tests/dictionaries/01base_file_mode2/tiramisu/base.py b/tests/dictionaries/01base_file_mode2/tiramisu/base.py new file mode 100644 index 000000000..58031f771 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/tiramisu/base.py @@ -0,0 +1,32 @@ +from importlib.machinery import SourceFileLoader as _SourceFileLoader +from importlib.util import spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec +class func: + pass + +def _load_functions(path): + global _SourceFileLoader, _spec_from_loader, _module_from_spec, func + loader = _SourceFileLoader('func', path) + spec = _spec_from_loader(loader.name, loader) + func_ = _module_from_spec(spec) + loader.exec_module(func_) + for function in dir(func_): + if function.startswith('_'): + continue + setattr(func, function, getattr(func_, function)) +_load_functions('tests/dictionaries/../eosfunc/test.py') +try: + from tiramisu3 import * +except: + from tiramisu import * +option_5 = FilenameOption(name="name", doc="name", default="/etc/file") +option_6 = StrOption(name="source", doc="source", default="file") +option_4 = BoolOption(name="activate", doc="activate", default=True) +optiondescription_3 = OptionDescription(name="file", doc="file", children=[option_5, option_6, option_4]) +optiondescription_3.impl_set_information('mode', 1755) +optiondescription_2 = OptionDescription(name="files", doc="files", children=[optiondescription_3]) +option_1 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +optiondescription_9 = OptionDescription(name="test_service", doc="test.service", children=[optiondescription_2, option_1, option_7]) +optiondescription_9.impl_set_information('type', "service") +optiondescription_8 = OptionDescription(name="services", doc="services", children=[optiondescription_9], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_8]) diff --git a/tests/dictionaries/01base_file_mode2/tiramisu/multi.py b/tests/dictionaries/01base_file_mode2/tiramisu/multi.py new file mode 100644 index 000000000..4985aeacd --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/tiramisu/multi.py @@ -0,0 +1,45 @@ +from importlib.machinery import SourceFileLoader as _SourceFileLoader +from importlib.util import spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec +class func: + pass + +def _load_functions(path): + global _SourceFileLoader, _spec_from_loader, _module_from_spec, func + loader = _SourceFileLoader('func', path) + spec = _spec_from_loader(loader.name, loader) + func_ = _module_from_spec(spec) + loader.exec_module(func_) + for function in dir(func_): + if function.startswith('_'): + continue + setattr(func, function, getattr(func_, function)) +_load_functions('tests/dictionaries/../eosfunc/test.py') +try: + from tiramisu3 import * +except: + from tiramisu import * +option_5 = FilenameOption(name="name", doc="name", default="/etc/file") +option_6 = StrOption(name="source", doc="source", default="file") +option_4 = BoolOption(name="activate", doc="activate", default=True) +optiondescription_3 = OptionDescription(name="file", doc="file", children=[option_5, option_6, option_4]) +optiondescription_3.impl_set_information('mode', 1755) +optiondescription_2 = OptionDescription(name="files", doc="files", children=[optiondescription_3]) +option_1 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +optiondescription_17 = OptionDescription(name="test_service", doc="test.service", children=[optiondescription_2, option_1, option_7]) +optiondescription_17.impl_set_information('type', "service") +optiondescription_16 = OptionDescription(name="services", doc="services", children=[optiondescription_17], properties=frozenset({"hidden"})) +optiondescription_15 = OptionDescription(name="1", doc="1", children=[optiondescription_16]) +option_12 = FilenameOption(name="name", doc="name", default="/etc/file") +option_13 = StrOption(name="source", doc="source", default="file") +option_11 = BoolOption(name="activate", doc="activate", default=True) +optiondescription_10 = OptionDescription(name="file", doc="file", children=[option_12, option_13, option_11]) +optiondescription_10.impl_set_information('mode', 1755) +optiondescription_9 = OptionDescription(name="files", doc="files", children=[optiondescription_10]) +option_8 = BoolOption(name="activate", doc="activate", default=True) +option_14 = BoolOption(name="manage", doc="manage", default=True) +optiondescription_20 = OptionDescription(name="test_service", doc="test.service", children=[optiondescription_9, option_8, option_14]) +optiondescription_20.impl_set_information('type', "service") +optiondescription_19 = OptionDescription(name="services", doc="services", children=[optiondescription_20], properties=frozenset({"hidden"})) +optiondescription_18 = OptionDescription(name="2", doc="2", children=[optiondescription_19]) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_15, optiondescription_18]) diff --git a/tests/dictionaries/01base_file_mode2/tmpl/file b/tests/dictionaries/01base_file_mode2/tmpl/file new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/tmpl/file @@ -0,0 +1 @@ +test diff --git a/tests/dictionaries/01base_file_mode2/xml/00-base.xml b/tests/dictionaries/01base_file_mode2/xml/00-base.xml new file mode 100644 index 000000000..217b92a94 --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/xml/00-base.xml @@ -0,0 +1,8 @@ + + + + + /etc/file + + + diff --git a/tests/dictionaries/01base_file_mode2/yml/00-base.yml b/tests/dictionaries/01base_file_mode2/yml/00-base.yml new file mode 100644 index 000000000..b30ec01cc --- /dev/null +++ b/tests/dictionaries/01base_file_mode2/yml/00-base.yml @@ -0,0 +1,7 @@ +version: '0.10' +services: +- service: + - name: test + file: + - mode: 1755 + text: /etc/file diff --git a/tests/test_others.py b/tests/test_others.py index 36a0fce69..b5504bbf4 100644 --- a/tests/test_others.py +++ b/tests/test_others.py @@ -80,9 +80,9 @@ def parse_dtd(elt_name, elts, space=0): if set(enum) == {'True', 'False'} or set(enum) == {'True', 'False', 'nil'}: # it's a boolean type_ = 'bool' - elif enum == ['number']: + elif enum == ['unix_permissions']: continue - elif f'{name}_type' in attributes and list(attributes[f'{name}_type'].itervalues()) == ['number']: + elif f'{name}_type' in attributes and list(attributes[f'{name}_type'].itervalues()) == ['unix_permissions']: type_ = 'int' else: type_ = 'str'