From 9c1589ca5399c1ca07c13555a533e15134fb76a0 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 13 May 2021 22:30:58 +0200 Subject: [PATCH] better systemd service support --- src/rougail/annotator/service.py | 54 +++++---- src/rougail/data/rougail.dtd | 3 + src/rougail/template/base.py | 65 ++++++++--- src/rougail/template/systemd.py | 90 ++++++++++----- src/rougail/update.py | 109 +++++++++--------- .../dictionaries/70service_engine/00-base.xml | 14 +++ .../dictionaries/70service_engine/__init__.py | 0 .../70service_engine/makedict/after.json | 14 +++ .../70service_engine/makedict/base.json | 5 + .../70service_engine/makedict/before.json | 14 +++ .../result/systemd/system/testsrv.service | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_engine/tiramisu/base.py | 22 ++++ .../70service_engine/tmpl/testsrv.service | 1 + .../dictionaries/70service_mount/00-base.xml | 13 +++ .../dictionaries/70service_mount/__init__.py | 0 .../70service_mount/makedict/after.json | 14 +++ .../70service_mount/makedict/base.json | 5 + .../70service_mount/makedict/before.json | 14 +++ .../result/systemd/system/testsrv.mount | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_mount/tiramisu/base.py | 23 ++++ .../70service_mount/tmpl/testsrv.mount | 1 + .../dictionaries/70service_target/00-base.xml | 13 +++ .../dictionaries/70service_target/__init__.py | 0 .../70service_target/makedict/after.json | 14 +++ .../70service_target/makedict/base.json | 5 + .../70service_target/makedict/before.json | 14 +++ .../system/test.target.wants/testsrv.service | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_target/tiramisu/base.py | 22 ++++ .../70service_target_engine/00-base.xml | 13 +++ .../70service_target_engine/__init__.py | 0 .../makedict/after.json | 14 +++ .../makedict/base.json | 5 + .../makedict/before.json | 14 +++ .../system/test.target.wants/testsrv.service | 1 + .../result/systemd/system/testsrv.service | 1 + .../result/tmpfiles.d/rougail.conf | 0 .../70service_target_engine/tiramisu/base.py | 23 ++++ .../tmpl/testsrv.service | 1 + .../80wrong_service_name/00-base.xml | 6 + .../80wrong_service_name/__init__.py | 0 .../80wrong_service_name/errno_76 | 0 tests/test_3_template.py | 6 +- 45 files changed, 496 insertions(+), 120 deletions(-) create mode 100644 tests/dictionaries/70service_engine/00-base.xml create mode 100644 tests/dictionaries/70service_engine/__init__.py create mode 100644 tests/dictionaries/70service_engine/makedict/after.json create mode 100644 tests/dictionaries/70service_engine/makedict/base.json create mode 100644 tests/dictionaries/70service_engine/makedict/before.json create mode 100644 tests/dictionaries/70service_engine/result/systemd/system/testsrv.service create mode 100644 tests/dictionaries/70service_engine/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_engine/tiramisu/base.py create mode 100644 tests/dictionaries/70service_engine/tmpl/testsrv.service create mode 100644 tests/dictionaries/70service_mount/00-base.xml create mode 100644 tests/dictionaries/70service_mount/__init__.py create mode 100644 tests/dictionaries/70service_mount/makedict/after.json create mode 100644 tests/dictionaries/70service_mount/makedict/base.json create mode 100644 tests/dictionaries/70service_mount/makedict/before.json create mode 100644 tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount create mode 100644 tests/dictionaries/70service_mount/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_mount/tiramisu/base.py create mode 100644 tests/dictionaries/70service_mount/tmpl/testsrv.mount create mode 100644 tests/dictionaries/70service_target/00-base.xml create mode 100644 tests/dictionaries/70service_target/__init__.py create mode 100644 tests/dictionaries/70service_target/makedict/after.json create mode 100644 tests/dictionaries/70service_target/makedict/base.json create mode 100644 tests/dictionaries/70service_target/makedict/before.json create mode 120000 tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service create mode 100644 tests/dictionaries/70service_target/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_target/tiramisu/base.py create mode 100644 tests/dictionaries/70service_target_engine/00-base.xml create mode 100644 tests/dictionaries/70service_target_engine/__init__.py create mode 100644 tests/dictionaries/70service_target_engine/makedict/after.json create mode 100644 tests/dictionaries/70service_target_engine/makedict/base.json create mode 100644 tests/dictionaries/70service_target_engine/makedict/before.json create mode 120000 tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service create mode 100644 tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service create mode 100644 tests/dictionaries/70service_target_engine/result/tmpfiles.d/rougail.conf create mode 100644 tests/dictionaries/70service_target_engine/tiramisu/base.py create mode 100644 tests/dictionaries/70service_target_engine/tmpl/testsrv.service create mode 100644 tests/dictionaries/80wrong_service_name/00-base.xml create mode 100644 tests/dictionaries/80wrong_service_name/__init__.py create mode 100644 tests/dictionaries/80wrong_service_name/errno_76 diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py index 69158b864..2f445a77f 100644 --- a/src/rougail/annotator/service.py +++ b/src/rougail/annotator/service.py @@ -28,15 +28,13 @@ from os.path import basename from typing import Tuple from rougail.i18n import _ -from rougail.utils import normalize_family +from rougail.utils import normalize_family, valid_variable_family_name from rougail.error import DictConsistencyError # a object's attribute has some annotations # that shall not be present in the exported (flatened) XML -ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespace', - 'remove_condition', 'path', 'instance_mode', 'index', - 'level', 'remove_fill', 'xmlfiles', 'type', 'reflector_name', - 'reflector_object',) -ALLOW_ATTRIBUT_NOT_MANAGE = ['file'] +ERASED_ATTRIBUTES = ('redefine', 'namespace', 'xmlfiles', 'disabled', 'name', 'manage') +ERASED_ATTRIBUTES2 = ('redefine', 'namespace', 'xmlfiles') +ALLOW_ATTRIBUT_NOT_MANAGE = ['file', 'engine', 'target'] class Annotator: @@ -72,6 +70,7 @@ class Annotator: self.objectspace.space.services.doc = 'services' self.objectspace.space.services.path = 'services' for service_name, service in self.objectspace.space.services.service.items(): + valid_variable_family_name(service_name, service.xmlfiles) activate_obj = self._generate_element('boolean', None, None, @@ -88,29 +87,34 @@ class Annotator: values, []).append(activate_obj) continue - if not isinstance(values, (dict, list)) or elttype in ERASED_ATTRIBUTES: + if elttype in ERASED_ATTRIBUTES: continue if not service.manage and elttype not in ALLOW_ATTRIBUT_NOT_MANAGE: msg = _(f'unmanage service cannot have "{elttype}"') raise DictConsistencyError(msg, 66, service.xmlfiles) - if elttype != 'ip': - eltname = elttype + 's' + if isinstance(values, (dict, list)): + if elttype != 'ip': + eltname = elttype + 's' + else: + eltname = elttype + path = '.'.join(['services', normalize_family(service_name), eltname]) + family = self._gen_family(eltname, + path, + service.xmlfiles, + with_informations=False, + ) + if isinstance(values, dict): + values = list(values.values()) + family.family = self.make_group_from_elts(service_name, + elttype, + values, + path, + ) + setattr(service, elttype, family) else: - eltname = elttype - path = '.'.join(['services', normalize_family(service_name), eltname]) - family = self._gen_family(eltname, - path, - service.xmlfiles, - with_informations=False, - ) - if isinstance(values, dict): - values = list(values.values()) - family.family = self.make_group_from_elts(service_name, - elttype, - values, - path, - ) - setattr(service, elttype, family) + if not hasattr(service, 'information'): + service.information = self.objectspace.information(service.xmlfiles) + setattr(service.information, elttype, values) manage = self._generate_element('boolean', None, None, @@ -157,7 +161,7 @@ class Annotator: '.'.join([subpath, 'activate']), ) for key in dir(elt): - if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES: + if key.startswith('_') or key.endswith('_type') or key in ERASED_ATTRIBUTES2: continue value = getattr(elt, key) if key == listname: diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd index 213297368..ecb107e7f 100644 --- a/src/rougail/data/rougail.dtd +++ b/src/rougail/data/rougail.dtd @@ -51,6 +51,9 @@ + + + diff --git a/src/rougail/template/base.py b/src/rougail/template/base.py index edcffaae7..ff2e7abf8 100644 --- a/src/rougail/template/base.py +++ b/src/rougail/template/base.py @@ -255,6 +255,7 @@ class RougailBaseTemplate: filevar: Dict, type_: str, service_name: str, + service_type: str, ) -> None: """Run templatisation on one file """ @@ -275,10 +276,11 @@ class RougailBaseTemplate: var = variable[idx] else: var = None - func = f'_instance_{type_}' + func = f'get_data_{type_}' data = getattr(self, func)(filevar, filename, service_name, + service_type, variable, idx, ) @@ -319,10 +321,26 @@ class RougailBaseTemplate: for included in (True, False): for service_obj in await self.config.option('services').list('all'): service_name = await service_obj.option.name() + service_type = await service_obj.information.get('type', 'service') if await service_obj.option('activate').value.get() is False: if included is False: - self.desactive_service(service_name) + self.desactive_service(service_name, service_type) continue + if not included: + engine = await service_obj.information.get('engine', None) + if engine: + self.instance_file({'engine': engine}, + 'service', + service_name, + service_type, + ) + target_name = await service_obj.information.get('target', None) + if target_name: + self.target_service(service_name, + target_name, + service_type, + engine is None, + ) for fills in await service_obj.list('optiondescription'): type_ = await fills.option.name() for fill_obj in await fills.list('all'): @@ -335,10 +353,14 @@ class RougailBaseTemplate: elif included is True: continue if fill['activate']: - self.instance_file(fill, type_, service_name) + self.instance_file(fill, + type_, + service_name, + service_type, + ) else: self.log.debug(_("Instantiation of file '{filename}' disabled")) - self.post_instance_service(service_name) + self.post_instance_service(service_name, service_type) self.post_instance() chdir(ori_dir) @@ -356,29 +378,42 @@ class RougailBaseTemplate: dico[key] = await obj.information.get(key, default_value) def desactive_service(self, - service_name: str, + *args, ): raise NotImplementedError(_('cannot desactivate a service')) - def post_instance_service(self, service_name): # pragma: no cover + def target_service(self, + service_name: str, + *args, + ): + raise NotImplementedError(_('cannot use target for the service {service_name}')) + + def post_instance_service(self, + *args, + ): # pragma: no cover pass def post_instance(self): # pragma: no cover pass - def _instance_ip(self, - *args, - ) -> None: # pragma: no cover + def get_data_ip(self, + *args, + ) -> None: # pragma: no cover raise NotImplementedError(_('cannot instanciate this service type ip')) - def _instance_files(self, - *args, - ) -> None: # pragma: no cover + def get_data_files(self, + *args, + ) -> None: # pragma: no cover raise NotImplementedError(_('cannot instanciate this service type file')) - def _instance_overrides(self, - *args, - ) -> None: # pragma: no cover + def get_data_service(self, + *args, + ) -> None: # pragma: no cover + raise NotImplementedError(_('cannot instanciate this service')) + + def get_data_overrides(self, + *args, + ) -> None: # pragma: no cover raise NotImplementedError(_('cannot instanciate this service type override')) async def load_variables(self, diff --git a/src/rougail/template/systemd.py b/src/rougail/template/systemd.py index 34ba60d11..c45f67350 100644 --- a/src/rougail/template/systemd.py +++ b/src/rougail/template/systemd.py @@ -38,9 +38,13 @@ IPAddressDeny=any """ -ROUGAIL_TMPL_TEMPLATE = """%def display(%%file, %%filename) +ROUGAIL_DEST = '/usr/local/lib' +ROUGAIL_GLOBAL_SYSTEMD_FILE = '/usr/lib/systemd/system' + + +ROUGAIL_TMPL_TEMPLATE = f"""%def display(%%file, %%filename) %if %%filename.startswith('/etc/') or %%filename.startswith('/var/') or %%filename.startswith('/srv/') -C %%filename %%file.mode %%file.owner %%file.group - /usr/local/lib%%filename +C %%filename %%file.mode %%file.owner %%file.group - {ROUGAIL_DEST}%%filename z %%filename - - - - - %end if %end def @@ -70,13 +74,14 @@ class RougailSystemdTemplate(RougailBaseTemplate): self.ip_per_service = None super().__init__(config, rougailconfig) - def _instance_files(self, - filevar: Dict, - destfile: str, - service_name: str, - variable, - idx: int, - ) -> tuple: + def get_data_files(self, + filevar: Dict, + destfile: str, + service_name: str, + service_type: str, + variable, + idx: int, + ) -> tuple: source = filevar['source'] if not isfile(source): # pragma: no cover raise FileNotFound(_(f"File {source} does not exist.")) @@ -88,27 +93,30 @@ class RougailSystemdTemplate(RougailBaseTemplate): var = None return tmp_file, None, destfile, var - def _instance_overrides(self, - filevar: Dict, - destfile, - service_name: str, - *args, - ) -> tuple: + def get_data_overrides(self, + filevar: Dict, + destfile, + service_name: str, + service_type: str, + *args, + ) -> tuple: source = filevar['source'] if not isfile(source): # pragma: no cover raise FileNotFound(_(f"File {source} does not exist.")) tmp_file = join(self.tmp_dir, source) service_name = filevar['name'] - return tmp_file, None, f'/systemd/system/{service_name}.service.d/rougail.conf', None + destfile = f'/systemd/system/{service_name}.{service_type}.d/rougail.conf' + return tmp_file, None, destfile, None - def _instance_ip(self, - filevar: Dict, - ip, - service_name: str, - var: Any, - idx: int, - *args, - ) -> tuple: + def get_data_ip(self, + filevar: Dict, + ip, + service_name: str, + service_type: str, + var: Any, + idx: int, + *args, + ) -> tuple: if self.ip_per_service is None: self.ip_per_service = [] if 'netmask' in filevar: @@ -120,19 +128,49 @@ class RougailSystemdTemplate(RougailBaseTemplate): elif ip: self.ip_per_service.append(ip) + def get_data_service(self, + servicevar: Dict, + info, + service_name: str, + service_type: str, + *args, + ): + filename = f'{service_name}.{service_type}' + tmp_file = join(self.tmp_dir, filename) + var = None + destfile = f'/systemd/system/{filename}' + return tmp_file, None, destfile, var + + def desactive_service(self, service_name: str, + service_type: str, ): - filename = f'{self.destinations_dir}/systemd/system/{service_name}.service' + filename = f'{self.destinations_dir}/systemd/system/{service_name}.{service_type}' makedirs(dirname(filename), exist_ok=True) symlink('/dev/null', filename) + def target_service(self, + service_name: str, + target_name: str, + service_type: str, + global_service: str, + ): + filename = f'{self.destinations_dir}/systemd/system/{target_name}.target.wants/{service_name}.{service_type}' + makedirs(dirname(filename), exist_ok=True) + if global_service: + source_filename = f'{ROUGAIL_GLOBAL_SYSTEMD_FILE}/{service_name}.{service_type}' + else: + source_filename = f'{ROUGAIL_DEST}/systemd/system/{service_name}.{service_type}' + symlink(source_filename, filename) + def post_instance_service(self, service_name: str, + service_type: str, ) -> None: # pragma: no cover if self.ip_per_service is None: return - destfile = f'/systemd/system/{service_name}.service.d/rougail_ip.conf' + destfile = f'/systemd/system/{service_name}.{service_type}.d/rougail_ip.conf' destfilename = join(self.destinations_dir, destfile[1:]) makedirs(dirname(destfilename), exist_ok=True) self.log.info(_(f"creole processing: '{destfilename}'")) diff --git a/src/rougail/update.py b/src/rougail/update.py index 7f90a8981..8ec66f43f 100644 --- a/src/rougail/update.py +++ b/src/rougail/update.py @@ -144,6 +144,63 @@ class RougailUpgrade: value.text = choices[0] variable.attrib['mandatory'] = 'True' + # convert group to leadership + groups = [] + if constraints is not None: + for constraint in constraints: + if constraint.tag == 'group': + constraints.remove(constraint) + groups.append(constraint) + for group in groups: + if group.attrib['leader'] in paths: + leader_obj = paths[group.attrib['leader']] + #FIXME name peut avoir "." il faut le virer + #FIXME si extra c'est un follower ! + if 'name' in group.attrib: + grpname = group.attrib['name'] + if 'description' in group.attrib: + description = group.attrib['description'] + else: + description = grpname + else: + grpname = leader_obj['variable'].attrib['name'] + if '.' in grpname: + grpname = grpname.rsplit('.', 1)[-1] + if 'description' in group.attrib: + description = group.attrib['description'] + elif 'description' in leader_obj['variable'].attrib: + description = leader_obj['variable'].attrib['description'] + else: + description = grpname + family = SubElement(leader_obj['parent'], 'family', name=grpname, description=description, leadership="True") + leader_obj['parent'].remove(leader_obj['variable']) + family.append(leader_obj['variable']) + else: + # append in group + follower = next(iter(group)) + leader_name = group.attrib['leader'] + if '.' in leader_name: + leader_path = leader_name.rsplit('.', 1)[0] + follower_path = leader_path + '.' + follower.text + else: + follower_path = follower.text + obj = paths[follower_path] + family = SubElement(obj['parent'], 'family', name=leader_name, leadership="True") + grpname = leader_name + for follower in group: + leader_name = group.attrib['leader'] + if '.' in leader_name: + leader_path = leader_name.rsplit('.', 1)[0] + follower_path = leader_path + '.' + follower.text + else: + follower_path = follower.text + follower_obj = paths[follower_path] + follower_obj['parent'].remove(follower_obj['variable']) + family.append(follower_obj['variable']) + if '.' in follower_path: + new_path = follower_path.rsplit('.', 1)[0] + '.' + grpname + '.' + follower_path.rsplit('.', 1)[1] + paths[new_path] = paths[follower_path] + # convert choice option valid_enums = [] if constraints is not None: @@ -207,58 +264,6 @@ class RougailUpgrade: for target in targets: if 'remove_choice' not in target.attrib or target.attrib['remove_choice'] != 'True': target.attrib['type'] = 'choice' - # convert group to leadership - groups = [] - if constraints is not None: - for constraint in constraints: - if constraint.tag == 'group': - constraints.remove(constraint) - groups.append(constraint) - for group in groups: - if group.attrib['leader'] in paths: - leader_obj = paths[group.attrib['leader']] - #FIXME name peut avoir "." il faut le virer - #FIXME si extra c'est un follower ! - if 'name' in group.attrib: - name = group.attrib['name'] - if 'description' in group.attrib: - description = group.attrib['description'] - else: - description = name - else: - name = leader_obj['variable'].attrib['name'] - if '.' in name: - name = name.rsplit('.', 1)[-1] - if 'description' in group.attrib: - description = group.attrib['description'] - elif 'description' in leader_obj['variable'].attrib: - description = leader_obj['variable'].attrib['description'] - else: - description = name - family = SubElement(leader_obj['parent'], 'family', name=name, description=description, leadership="True") - leader_obj['parent'].remove(leader_obj['variable']) - family.append(leader_obj['variable']) - else: - # append in group - follower = next(iter(group)) - leader_name = group.attrib['leader'] - if '.' in leader_name: - leader_path = leader_name.rsplit('.', 1)[0] - follower_path = leader_path + '.' + follower.text - else: - follower_path = follower.text - obj = paths[follower_path] - family = SubElement(obj['parent'], 'family', name=leader_name, leadership="True") - for follower in group: - leader_name = group.attrib['leader'] - if '.' in leader_name: - leader_path = leader_name.rsplit('.', 1)[0] - follower_path = leader_path + '.' + follower.text - else: - follower_path = follower.text - follower_obj = paths[follower_path] - follower_obj['parent'].remove(follower_obj['variable']) - family.append(follower_obj['variable']) return root def _get_path_variables(self, variables, is_variable_namespace, path, dico=None): diff --git a/tests/dictionaries/70service_engine/00-base.xml b/tests/dictionaries/70service_engine/00-base.xml new file mode 100644 index 000000000..a84500bde --- /dev/null +++ b/tests/dictionaries/70service_engine/00-base.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/tests/dictionaries/70service_engine/__init__.py b/tests/dictionaries/70service_engine/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_engine/makedict/after.json b/tests/dictionaries/70service_engine/makedict/after.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_engine/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_engine/makedict/base.json b/tests/dictionaries/70service_engine/makedict/base.json new file mode 100644 index 000000000..d89ef3da8 --- /dev/null +++ b/tests/dictionaries/70service_engine/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_engine/makedict/before.json b/tests/dictionaries/70service_engine/makedict/before.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_engine/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_engine/result/systemd/system/testsrv.service b/tests/dictionaries/70service_engine/result/systemd/system/testsrv.service new file mode 100644 index 000000000..bd51bf63f --- /dev/null +++ b/tests/dictionaries/70service_engine/result/systemd/system/testsrv.service @@ -0,0 +1 @@ +oui diff --git a/tests/dictionaries/70service_engine/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_engine/result/tmpfiles.d/rougail.conf new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_engine/tiramisu/base.py b/tests/dictionaries/70service_engine/tiramisu/base.py new file mode 100644 index 000000000..bbf9ec623 --- /dev/null +++ b/tests/dictionaries/70service_engine/tiramisu/base.py @@ -0,0 +1,22 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('engine', "creole") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_engine/tmpl/testsrv.service b/tests/dictionaries/70service_engine/tmpl/testsrv.service new file mode 100644 index 000000000..a29cfeaf3 --- /dev/null +++ b/tests/dictionaries/70service_engine/tmpl/testsrv.service @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/70service_mount/00-base.xml b/tests/dictionaries/70service_mount/00-base.xml new file mode 100644 index 000000000..92889e45a --- /dev/null +++ b/tests/dictionaries/70service_mount/00-base.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/tests/dictionaries/70service_mount/__init__.py b/tests/dictionaries/70service_mount/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_mount/makedict/after.json b/tests/dictionaries/70service_mount/makedict/after.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_mount/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_mount/makedict/base.json b/tests/dictionaries/70service_mount/makedict/base.json new file mode 100644 index 000000000..d89ef3da8 --- /dev/null +++ b/tests/dictionaries/70service_mount/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_mount/makedict/before.json b/tests/dictionaries/70service_mount/makedict/before.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_mount/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount b/tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount new file mode 100644 index 000000000..bd51bf63f --- /dev/null +++ b/tests/dictionaries/70service_mount/result/systemd/system/testsrv.mount @@ -0,0 +1 @@ +oui diff --git a/tests/dictionaries/70service_mount/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_mount/result/tmpfiles.d/rougail.conf new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_mount/tiramisu/base.py b/tests/dictionaries/70service_mount/tiramisu/base.py new file mode 100644 index 000000000..5f4776711 --- /dev/null +++ b/tests/dictionaries/70service_mount/tiramisu/base.py @@ -0,0 +1,23 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('type', "mount") +option_5.impl_set_information('engine', "creole") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_mount/tmpl/testsrv.mount b/tests/dictionaries/70service_mount/tmpl/testsrv.mount new file mode 100644 index 000000000..a29cfeaf3 --- /dev/null +++ b/tests/dictionaries/70service_mount/tmpl/testsrv.mount @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/70service_target/00-base.xml b/tests/dictionaries/70service_target/00-base.xml new file mode 100644 index 000000000..9d0494a2c --- /dev/null +++ b/tests/dictionaries/70service_target/00-base.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/tests/dictionaries/70service_target/__init__.py b/tests/dictionaries/70service_target/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_target/makedict/after.json b/tests/dictionaries/70service_target/makedict/after.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_target/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target/makedict/base.json b/tests/dictionaries/70service_target/makedict/base.json new file mode 100644 index 000000000..d89ef3da8 --- /dev/null +++ b/tests/dictionaries/70service_target/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_target/makedict/before.json b/tests/dictionaries/70service_target/makedict/before.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_target/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service b/tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service new file mode 120000 index 000000000..c8a389334 --- /dev/null +++ b/tests/dictionaries/70service_target/result/systemd/system/test.target.wants/testsrv.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/testsrv.service \ No newline at end of file diff --git a/tests/dictionaries/70service_target/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_target/result/tmpfiles.d/rougail.conf new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_target/tiramisu/base.py b/tests/dictionaries/70service_target/tiramisu/base.py new file mode 100644 index 000000000..4795e3b37 --- /dev/null +++ b/tests/dictionaries/70service_target/tiramisu/base.py @@ -0,0 +1,22 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('target', "test") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_target_engine/00-base.xml b/tests/dictionaries/70service_target_engine/00-base.xml new file mode 100644 index 000000000..313e8062b --- /dev/null +++ b/tests/dictionaries/70service_target_engine/00-base.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/tests/dictionaries/70service_target_engine/__init__.py b/tests/dictionaries/70service_target_engine/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_target_engine/makedict/after.json b/tests/dictionaries/70service_target_engine/makedict/after.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/makedict/after.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target_engine/makedict/base.json b/tests/dictionaries/70service_target_engine/makedict/base.json new file mode 100644 index 000000000..d89ef3da8 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/makedict/base.json @@ -0,0 +1,5 @@ +{ + "rougail.general.mode_conteneur_actif": "oui", + "services.testsrv.activate": true, + "services.testsrv.manage": true +} diff --git a/tests/dictionaries/70service_target_engine/makedict/before.json b/tests/dictionaries/70service_target_engine/makedict/before.json new file mode 100644 index 000000000..c8847b435 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/makedict/before.json @@ -0,0 +1,14 @@ +{ + "rougail.general.mode_conteneur_actif": { + "owner": "default", + "value": "oui" + }, + "services.testsrv.activate": { + "owner": "default", + "value": true + }, + "services.testsrv.manage": { + "owner": "default", + "value": true + } +} diff --git a/tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service b/tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service new file mode 120000 index 000000000..4cc00d1a3 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/result/systemd/system/test.target.wants/testsrv.service @@ -0,0 +1 @@ +/usr/local/lib/systemd/system/testsrv.service \ No newline at end of file diff --git a/tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service b/tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service new file mode 100644 index 000000000..a29cfeaf3 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/result/systemd/system/testsrv.service @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/70service_target_engine/result/tmpfiles.d/rougail.conf b/tests/dictionaries/70service_target_engine/result/tmpfiles.d/rougail.conf new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/70service_target_engine/tiramisu/base.py b/tests/dictionaries/70service_target_engine/tiramisu/base.py new file mode 100644 index 000000000..4701a3b17 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/tiramisu/base.py @@ -0,0 +1,23 @@ +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec +loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py') +spec = spec_from_loader(loader.name, loader) +func = module_from_spec(spec) +loader.exec_module(func) +for key, value in dict(locals()).items(): + if key != ['SourceFileLoader', 'func']: + setattr(func, key, value) +try: + from tiramisu3 import * +except: + from tiramisu import * +option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"})) +option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"})) +option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2]) +option_6 = BoolOption(name="activate", doc="activate", default=True) +option_7 = BoolOption(name="manage", doc="manage", default=True) +option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6, option_7]) +option_5.impl_set_information('target', "test") +option_5.impl_set_information('engine', "none") +option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"})) +option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4]) diff --git a/tests/dictionaries/70service_target_engine/tmpl/testsrv.service b/tests/dictionaries/70service_target_engine/tmpl/testsrv.service new file mode 100644 index 000000000..a29cfeaf3 --- /dev/null +++ b/tests/dictionaries/70service_target_engine/tmpl/testsrv.service @@ -0,0 +1 @@ +%%mode_conteneur_actif diff --git a/tests/dictionaries/80wrong_service_name/00-base.xml b/tests/dictionaries/80wrong_service_name/00-base.xml new file mode 100644 index 000000000..a7f31c935 --- /dev/null +++ b/tests/dictionaries/80wrong_service_name/00-base.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/dictionaries/80wrong_service_name/__init__.py b/tests/dictionaries/80wrong_service_name/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dictionaries/80wrong_service_name/errno_76 b/tests/dictionaries/80wrong_service_name/errno_76 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_3_template.py b/tests/test_3_template.py index 1bb423df4..6ac69cee3 100644 --- a/tests/test_3_template.py +++ b/tests/test_3_template.py @@ -1,4 +1,4 @@ -from os import listdir, mkdir +from os import listdir, mkdir, readlink from os.path import join, isdir, isfile, islink from shutil import rmtree from pytest import fixture, mark @@ -82,7 +82,9 @@ async def test_dictionary(test_dir): assert list_templates == list_results for result in list_results: template_file = join(dest_dir, result) - if islink(template_file) and islink(join(test_dir, 'result', result)): + assert islink(template_file) == islink(join(test_dir, 'result', result)) + if islink(template_file): + assert readlink(template_file) == readlink(join(test_dir, 'result', result)) continue if not isfile(template_file): raise Exception(f'{template_file} is not generated')