better systemd service support

This commit is contained in:
Emmanuel Garette 2021-05-13 22:30:58 +02:00
parent 20f329d433
commit 9c1589ca53
45 changed files with 496 additions and 120 deletions

View File

@ -28,15 +28,13 @@ from os.path import basename
from typing import Tuple from typing import Tuple
from rougail.i18n import _ 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 from rougail.error import DictConsistencyError
# a object's attribute has some annotations # a object's attribute has some annotations
# that shall not be present in the exported (flatened) XML # that shall not be present in the exported (flatened) XML
ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespace', ERASED_ATTRIBUTES = ('redefine', 'namespace', 'xmlfiles', 'disabled', 'name', 'manage')
'remove_condition', 'path', 'instance_mode', 'index', ERASED_ATTRIBUTES2 = ('redefine', 'namespace', 'xmlfiles')
'level', 'remove_fill', 'xmlfiles', 'type', 'reflector_name', ALLOW_ATTRIBUT_NOT_MANAGE = ['file', 'engine', 'target']
'reflector_object',)
ALLOW_ATTRIBUT_NOT_MANAGE = ['file']
class Annotator: class Annotator:
@ -72,6 +70,7 @@ class Annotator:
self.objectspace.space.services.doc = 'services' self.objectspace.space.services.doc = 'services'
self.objectspace.space.services.path = 'services' self.objectspace.space.services.path = 'services'
for service_name, service in self.objectspace.space.services.service.items(): 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', activate_obj = self._generate_element('boolean',
None, None,
None, None,
@ -88,29 +87,34 @@ class Annotator:
values, values,
[]).append(activate_obj) []).append(activate_obj)
continue continue
if not isinstance(values, (dict, list)) or elttype in ERASED_ATTRIBUTES: if elttype in ERASED_ATTRIBUTES:
continue continue
if not service.manage and elttype not in ALLOW_ATTRIBUT_NOT_MANAGE: if not service.manage and elttype not in ALLOW_ATTRIBUT_NOT_MANAGE:
msg = _(f'unmanage service cannot have "{elttype}"') msg = _(f'unmanage service cannot have "{elttype}"')
raise DictConsistencyError(msg, 66, service.xmlfiles) raise DictConsistencyError(msg, 66, service.xmlfiles)
if elttype != 'ip': if isinstance(values, (dict, list)):
eltname = elttype + 's' 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: else:
eltname = elttype if not hasattr(service, 'information'):
path = '.'.join(['services', normalize_family(service_name), eltname]) service.information = self.objectspace.information(service.xmlfiles)
family = self._gen_family(eltname, setattr(service.information, elttype, values)
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)
manage = self._generate_element('boolean', manage = self._generate_element('boolean',
None, None,
None, None,
@ -157,7 +161,7 @@ class Annotator:
'.'.join([subpath, 'activate']), '.'.join([subpath, 'activate']),
) )
for key in dir(elt): 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 continue
value = getattr(elt, key) value = getattr(elt, key)
if key == listname: if key == listname:

View File

@ -51,6 +51,9 @@
<!ATTLIST service manage (True|False) "True"> <!ATTLIST service manage (True|False) "True">
<!ATTLIST service servicelist CDATA #IMPLIED> <!ATTLIST service servicelist CDATA #IMPLIED>
<!ATTLIST service disabled (True|False) "False"> <!ATTLIST service disabled (True|False) "False">
<!ATTLIST service engine (none|creole|jinja2) #IMPLIED>
<!ATTLIST service target CDATA #IMPLIED>
<!ATTLIST service type (service|mount) "service">
<!ELEMENT ip (#PCDATA)> <!ELEMENT ip (#PCDATA)>
<!ATTLIST ip iplist CDATA #IMPLIED> <!ATTLIST ip iplist CDATA #IMPLIED>

View File

@ -255,6 +255,7 @@ class RougailBaseTemplate:
filevar: Dict, filevar: Dict,
type_: str, type_: str,
service_name: str, service_name: str,
service_type: str,
) -> None: ) -> None:
"""Run templatisation on one file """Run templatisation on one file
""" """
@ -275,10 +276,11 @@ class RougailBaseTemplate:
var = variable[idx] var = variable[idx]
else: else:
var = None var = None
func = f'_instance_{type_}' func = f'get_data_{type_}'
data = getattr(self, func)(filevar, data = getattr(self, func)(filevar,
filename, filename,
service_name, service_name,
service_type,
variable, variable,
idx, idx,
) )
@ -319,10 +321,26 @@ class RougailBaseTemplate:
for included in (True, False): for included in (True, False):
for service_obj in await self.config.option('services').list('all'): for service_obj in await self.config.option('services').list('all'):
service_name = await service_obj.option.name() 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 await service_obj.option('activate').value.get() is False:
if included is False: if included is False:
self.desactive_service(service_name) self.desactive_service(service_name, service_type)
continue 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'): for fills in await service_obj.list('optiondescription'):
type_ = await fills.option.name() type_ = await fills.option.name()
for fill_obj in await fills.list('all'): for fill_obj in await fills.list('all'):
@ -335,10 +353,14 @@ class RougailBaseTemplate:
elif included is True: elif included is True:
continue continue
if fill['activate']: if fill['activate']:
self.instance_file(fill, type_, service_name) self.instance_file(fill,
type_,
service_name,
service_type,
)
else: else:
self.log.debug(_("Instantiation of file '{filename}' disabled")) 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() self.post_instance()
chdir(ori_dir) chdir(ori_dir)
@ -356,29 +378,42 @@ class RougailBaseTemplate:
dico[key] = await obj.information.get(key, default_value) dico[key] = await obj.information.get(key, default_value)
def desactive_service(self, def desactive_service(self,
service_name: str, *args,
): ):
raise NotImplementedError(_('cannot desactivate a service')) 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 pass
def post_instance(self): # pragma: no cover def post_instance(self): # pragma: no cover
pass pass
def _instance_ip(self, def get_data_ip(self,
*args, *args,
) -> None: # pragma: no cover ) -> None: # pragma: no cover
raise NotImplementedError(_('cannot instanciate this service type ip')) raise NotImplementedError(_('cannot instanciate this service type ip'))
def _instance_files(self, def get_data_files(self,
*args, *args,
) -> None: # pragma: no cover ) -> None: # pragma: no cover
raise NotImplementedError(_('cannot instanciate this service type file')) raise NotImplementedError(_('cannot instanciate this service type file'))
def _instance_overrides(self, def get_data_service(self,
*args, *args,
) -> None: # pragma: no cover ) -> 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')) raise NotImplementedError(_('cannot instanciate this service type override'))
async def load_variables(self, async def load_variables(self,

View File

@ -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/') %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 - - - - - z %%filename - - - - -
%end if %end if
%end def %end def
@ -70,13 +74,14 @@ class RougailSystemdTemplate(RougailBaseTemplate):
self.ip_per_service = None self.ip_per_service = None
super().__init__(config, rougailconfig) super().__init__(config, rougailconfig)
def _instance_files(self, def get_data_files(self,
filevar: Dict, filevar: Dict,
destfile: str, destfile: str,
service_name: str, service_name: str,
variable, service_type: str,
idx: int, variable,
) -> tuple: idx: int,
) -> tuple:
source = filevar['source'] source = filevar['source']
if not isfile(source): # pragma: no cover if not isfile(source): # pragma: no cover
raise FileNotFound(_(f"File {source} does not exist.")) raise FileNotFound(_(f"File {source} does not exist."))
@ -88,27 +93,30 @@ class RougailSystemdTemplate(RougailBaseTemplate):
var = None var = None
return tmp_file, None, destfile, var return tmp_file, None, destfile, var
def _instance_overrides(self, def get_data_overrides(self,
filevar: Dict, filevar: Dict,
destfile, destfile,
service_name: str, service_name: str,
*args, service_type: str,
) -> tuple: *args,
) -> tuple:
source = filevar['source'] source = filevar['source']
if not isfile(source): # pragma: no cover if not isfile(source): # pragma: no cover
raise FileNotFound(_(f"File {source} does not exist.")) raise FileNotFound(_(f"File {source} does not exist."))
tmp_file = join(self.tmp_dir, source) tmp_file = join(self.tmp_dir, source)
service_name = filevar['name'] 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, def get_data_ip(self,
filevar: Dict, filevar: Dict,
ip, ip,
service_name: str, service_name: str,
var: Any, service_type: str,
idx: int, var: Any,
*args, idx: int,
) -> tuple: *args,
) -> tuple:
if self.ip_per_service is None: if self.ip_per_service is None:
self.ip_per_service = [] self.ip_per_service = []
if 'netmask' in filevar: if 'netmask' in filevar:
@ -120,19 +128,49 @@ class RougailSystemdTemplate(RougailBaseTemplate):
elif ip: elif ip:
self.ip_per_service.append(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, def desactive_service(self,
service_name: str, 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) makedirs(dirname(filename), exist_ok=True)
symlink('/dev/null', filename) 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, def post_instance_service(self,
service_name: str, service_name: str,
service_type: str,
) -> None: # pragma: no cover ) -> None: # pragma: no cover
if self.ip_per_service is None: if self.ip_per_service is None:
return 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:]) destfilename = join(self.destinations_dir, destfile[1:])
makedirs(dirname(destfilename), exist_ok=True) makedirs(dirname(destfilename), exist_ok=True)
self.log.info(_(f"creole processing: '{destfilename}'")) self.log.info(_(f"creole processing: '{destfilename}'"))

View File

@ -144,6 +144,63 @@ class RougailUpgrade:
value.text = choices[0] value.text = choices[0]
variable.attrib['mandatory'] = 'True' 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 # convert choice option
valid_enums = [] valid_enums = []
if constraints is not None: if constraints is not None:
@ -207,58 +264,6 @@ class RougailUpgrade:
for target in targets: for target in targets:
if 'remove_choice' not in target.attrib or target.attrib['remove_choice'] != 'True': if 'remove_choice' not in target.attrib or target.attrib['remove_choice'] != 'True':
target.attrib['type'] = 'choice' 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 return root
def _get_path_variables(self, variables, is_variable_namespace, path, dico=None): def _get_path_variables(self, variables, is_variable_namespace, path, dico=None):

View File

@ -0,0 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10">
<services>
<service name="testsrv" engine="creole">
</service>
</services>
<variables>
<family name="general" description="général">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>oui</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -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
}
}

View File

@ -0,0 +1,5 @@
{
"rougail.general.mode_conteneur_actif": "oui",
"services.testsrv.activate": true,
"services.testsrv.manage": true
}

View File

@ -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
}
}

View File

@ -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])

View File

@ -0,0 +1 @@
%%mode_conteneur_actif

View File

@ -0,0 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10">
<services>
<service name="testsrv" type="mount" engine="creole"/>
</services>
<variables>
<family name="general" description="général">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>oui</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -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
}
}

View File

@ -0,0 +1,5 @@
{
"rougail.general.mode_conteneur_actif": "oui",
"services.testsrv.activate": true,
"services.testsrv.manage": true
}

View File

@ -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
}
}

View File

@ -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])

View File

@ -0,0 +1 @@
%%mode_conteneur_actif

View File

@ -0,0 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10">
<services>
<service name="testsrv" target="test"/>
</services>
<variables>
<family name="general" description="général">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>oui</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -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
}
}

View File

@ -0,0 +1,5 @@
{
"rougail.general.mode_conteneur_actif": "oui",
"services.testsrv.activate": true,
"services.testsrv.manage": true
}

View File

@ -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
}
}

View File

@ -0,0 +1 @@
/usr/lib/systemd/system/testsrv.service

View File

@ -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])

View File

@ -0,0 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10">
<services>
<service name="testsrv" target="test" engine="none"/>
</services>
<variables>
<family name="general" description="général">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>oui</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -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
}
}

View File

@ -0,0 +1,5 @@
{
"rougail.general.mode_conteneur_actif": "oui",
"services.testsrv.activate": true,
"services.testsrv.manage": true
}

View File

@ -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
}
}

View File

@ -0,0 +1 @@
/usr/local/lib/systemd/system/testsrv.service

View File

@ -0,0 +1 @@
%%mode_conteneur_actif

View File

@ -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])

View File

@ -0,0 +1 @@
%%mode_conteneur_actif

View File

@ -0,0 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10">
<services>
<service name="testsrv.mount"/>
</services>
</rougail>

View File

@ -1,4 +1,4 @@
from os import listdir, mkdir from os import listdir, mkdir, readlink
from os.path import join, isdir, isfile, islink from os.path import join, isdir, isfile, islink
from shutil import rmtree from shutil import rmtree
from pytest import fixture, mark from pytest import fixture, mark
@ -82,7 +82,9 @@ async def test_dictionary(test_dir):
assert list_templates == list_results assert list_templates == list_results
for result in list_results: for result in list_results:
template_file = join(dest_dir, result) 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 continue
if not isfile(template_file): if not isfile(template_file):
raise Exception(f'{template_file} is not generated') raise Exception(f'{template_file} is not generated')