can templating only one file

This commit is contained in:
egarette@silique.fr 2023-01-23 22:55:17 +01:00
parent f213f5777b
commit 2fd3c22db9
3 changed files with 177 additions and 67 deletions

View file

@ -292,11 +292,11 @@ class RougailBaseTemplate:
copy(join(templates_dir, filename), self.tmp_dir) copy(join(templates_dir, filename), self.tmp_dir)
self.patch_template(filename, templates_dir) self.patch_template(filename, templates_dir)
def instance_file(self, def _instance_file(self,
filevar: Dict, filevar: Dict,
type_: str, type_: str,
service_name: str, service_name: str,
) -> str: ) -> str:
"""Run templatisation on one file """Run templatisation on one file
""" """
if 'variable' in filevar: if 'variable' in filevar:
@ -328,7 +328,7 @@ class RougailBaseTemplate:
filename, source, true_destfilename, var = data filename, source, true_destfilename, var = data
self.log.info(_(f'Instantiating file "{filename}"')) self.log.info(_(f'Instantiating file "{filename}"'))
if not true_destfilename.startswith('/'): if not true_destfilename.startswith('/'):
raise Exception(f'true_destfilename must starts with a / in function {func}') raise TemplateError(f'true_destfilename must starts with a / in function {func}')
destfilename = join(self.destinations_dir, true_destfilename[1:]) destfilename = join(self.destinations_dir, true_destfilename[1:])
makedirs(dirname(destfilename), exist_ok=True) makedirs(dirname(destfilename), exist_ok=True)
self.log.info(_(f"{filevar['engine']} processing: '{destfilename}'")) self.log.info(_(f"{filevar['engine']} processing: '{destfilename}'"))
@ -366,6 +366,47 @@ class RougailBaseTemplate:
is_service_namespace, is_service_namespace,
) )
async def instance_file(self, template_name) -> None:
if not self.rougail_variables_dict:
await self.load_variables()
self.prepare_templates()
for service_obj in await self.config.option('services').list('all'):
service_name = await service_obj.option.description()
service_desactived = await service_obj.option('activate').value.get() is False
for fills in await service_obj.list('optiondescription'):
type_ = await fills.option.name()
for fill_obj in await fills.list('all'):
fill = await fill_obj.value.dict()
self.get_default(type_, fill, fill_obj)
await self.get_informations(type_, fill, fill_obj)
if fill['source'] != template_name:
continue
if service_desactived:
raise TemplateError(f'template {template_name} is inside a desactived service')
if 'included' in fill and fill['included'] != 'no':
raise TemplateError(f'template {template_name} is an included file')
if not fill['activate']:
raise TemplateError(f'template {template_name} is desactived')
try:
ori_dir = getcwd()
except FileNotFoundError:
ori_dir = None
chdir(self.tmp_dir)
try:
self._instance_file(fill,
type_,
service_name,
)
except Exception as err:
if ori_dir is not None:
chdir(ori_dir)
raise err from err
if ori_dir is not None:
chdir(ori_dir)
return
raise TemplateError(f'Cannot find template {template_name}')
async def instance_files(self) -> None: async def instance_files(self) -> None:
"""Run templatisation on all files """Run templatisation on all files
""" """
@ -377,11 +418,7 @@ class RougailBaseTemplate:
try: try:
if not self.rougail_variables_dict: if not self.rougail_variables_dict:
await self.load_variables() await self.load_variables()
for templates_dir in self.templates_dir: self.prepare_templates()
for template in listdir(templates_dir):
self.prepare_template(template,
templates_dir,
)
files_to_delete = [] files_to_delete = []
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'):
@ -393,10 +430,10 @@ class RougailBaseTemplate:
if not included: if not included:
engine = await service_obj.information.get('engine', None) engine = await service_obj.information.get('engine', None)
if engine: if engine:
self.instance_file({'engine': engine}, self._instance_file({'engine': engine},
'service', 'service',
service_name, service_name,
) )
target_name = await service_obj.information.get('target', None) target_name = await service_obj.information.get('target', None)
if target_name: if target_name:
self.target_service(service_name, self.target_service(service_name,
@ -416,10 +453,10 @@ class RougailBaseTemplate:
elif included is True: elif included is True:
continue continue
if fill['activate']: if fill['activate']:
destfilenames = self.instance_file(fill, destfilenames = self._instance_file(fill,
type_, type_,
service_name, service_name,
) )
if included and fill.get('included', 'no') == 'content': if included and fill.get('included', 'no') == 'content':
files_to_delete.extend(destfilenames) files_to_delete.extend(destfilenames)
elif 'name' in fill: elif 'name' in fill:
@ -441,6 +478,13 @@ class RougailBaseTemplate:
if ori_dir is not None: if ori_dir is not None:
chdir(ori_dir) chdir(ori_dir)
def prepare_templates(self):
for templates_dir in self.templates_dir:
for template in listdir(templates_dir):
self.prepare_template(template,
templates_dir,
)
def get_default(self, def get_default(self,
type_: str, type_: str,
dico: dict, dico: dict,
@ -527,7 +571,6 @@ class RougailBaseTemplate:
if not isfile(source): # pragma: no cover if not isfile(source): # pragma: no cover
raise FileNotFound(_(f'Source file "{source}" does not exist in {", ".join(self.templates_dir)}')) raise FileNotFound(_(f'Source file "{source}" does not exist in {", ".join(self.templates_dir)}'))
tmp_file = join(self.tmp_dir, source) tmp_file = join(self.tmp_dir, source)
#self.instance_file(fill, 'files')
if variable: if variable:
var = variable[idx] var = variable[idx]
else: else:

View file

@ -2,7 +2,7 @@
<rougail version="0.10"> <rougail version="0.10">
<services> <services>
<service name="testsrv" engine="cheetah"> <service name="testsrv" engine="cheetah">
</service> </service>
</services> </services>
<variables> <variables>
<family name="general" description="général"> <family name="general" description="général">

View file

@ -6,6 +6,8 @@ from lxml.etree import parse
from tiramisu import Config from tiramisu import Config
from rougail import RougailConfig, RougailBaseTemplate, RougailSystemdTemplate from rougail import RougailConfig, RougailBaseTemplate, RougailSystemdTemplate
from rougail.error import TemplateError
from jinja2.exceptions import TemplateNotFound
template_dirs = 'tests/dictionaries' template_dirs = 'tests/dictionaries'
@ -15,7 +17,7 @@ test_ok = {f for f in listdir(template_dirs) if not f.startswith('_') and isdir(
test_ok -= excludes test_ok -= excludes
test_ok = list(test_ok) test_ok = list(test_ok)
test_ok.sort() test_ok.sort()
#test_ok = ['01base_file_include_content'] #test_ok = ['70service_servicelist_file']
@fixture(scope="module", params=test_ok) @fixture(scope="module", params=test_ok)
@ -39,7 +41,7 @@ def find_files(dirname: str,
files.add(join(*root_file)) files.add(join(*root_file))
async def template(test_dir, filename, root, engine_name): async def templates(test_dir, filename, root, engine_name, only_one=False):
test_dir = join(template_dirs, test_dir) test_dir = join(template_dirs, test_dir)
tmp_dir = join(test_dir, '..', 'tmp') tmp_dir = join(test_dir, '..', 'tmp')
@ -55,13 +57,7 @@ async def template(test_dir, filename, root, engine_name):
funcs_file = join(template_dirs, '../eosfunc/test.py') funcs_file = join(template_dirs, '../eosfunc/test.py')
distrib_dir = join(test_dir, 'tmpl') distrib_dir = join(test_dir, 'tmpl')
if isdir(tmp_dir):
rmtree(tmp_dir)
mkdir(tmp_dir)
dest_dir = join(test_dir, 'dest') dest_dir = join(test_dir, 'dest')
if isdir(dest_dir):
rmtree(dest_dir)
mkdir(dest_dir)
RougailConfig['patches_dir'] = join(test_dir, 'patches') RougailConfig['patches_dir'] = join(test_dir, 'patches')
RougailConfig['templates_dir'] = distrib_dir RougailConfig['templates_dir'] = distrib_dir
RougailConfig['tmp_dir'] = tmp_dir RougailConfig['tmp_dir'] = tmp_dir
@ -79,39 +75,112 @@ async def template(test_dir, filename, root, engine_name):
engine = RougailBaseTemplate(config) engine = RougailBaseTemplate(config)
else: else:
engine = RougailSystemdTemplate(config) engine = RougailSystemdTemplate(config)
await engine.instance_files() if not only_one:
list_templates = set() list_templates = [None]
if isdir(dest_dir): else:
find_files(dest_dir, list_templates = set()
find_files(distrib_dir,
[], [],
list_templates, list_templates,
) )
list_results = set() for template in list_templates:
if isdir(join(test_dir, 'result')): if isdir(tmp_dir):
find_files(join(test_dir, 'result'), rmtree(tmp_dir)
[], mkdir(tmp_dir)
list_results, if isdir(dest_dir):
) rmtree(dest_dir)
if engine_name == 'base' and 'tmpfiles.d/0rougail.conf' in list_results: mkdir(dest_dir)
list_results.remove('tmpfiles.d/0rougail.conf') if template is None:
assert list_templates == list_results, f'error with {test_dir}:' await engine.instance_files()
for result in list_results: list_results = set()
template_file = join(dest_dir, result) if isdir(join(test_dir, 'result')):
assert islink(template_file) == islink(join(test_dir, 'result', result)) find_files(join(test_dir, 'result'),
if islink(template_file): [],
assert readlink(template_file) == readlink(join(test_dir, 'result', result)) list_results,
continue )
if not isfile(template_file): else:
raise Exception(f'{template_file} is not generated') list_results = set()
with open(join(test_dir, 'result', result), 'r') as fh: included = False
result_file = fh.read() activate = True
with open(template_file, 'r') as fh: for service in await config.option('services').option.list('all'):
generated_file = fh.read() names = [await o.option.name() for o in await service.option.list('optiondescription')]
assert result_file == generated_file, f'{template_file} content : \n{generated_file}\nexpected: \nresult_file\n' if 'files' in names:
if isdir(dest_dir): for file in await service.option('files').list('optiondescription'):
rmtree(dest_dir) if not await file.option('source').value.get() == template:
if isdir(tmp_dir): continue
rmtree(tmp_dir) included = await file.information.get('included', 'no') != 'no'
values = await file.option('name').value.get()
if isinstance(values, list):
for value in values:
list_results.add(value[1:])
else:
list_results.add(values[1:])
if not await file.option('activate').value.get():
activate = False
# if template is an overrides
if not list_results and 'overrides' in names:
for override in await service.option('overrides').list('optiondescription'):
if await override.option.description() == template:
return
# if template is a service
if not list_results and template == await service.option.description() and await service.information.get('engine', None):
return
#this file is include and not declared
if template.startswith('inc') and not list_results:
return
try:
await engine.instance_file(template)
except TemplateError as err:
if 'No such file or directory' in str(err):
continue
if included or not activate:
continue
raise err from err
except TemplateNotFound:
continue
assert activate, 'template should be desactivate'
assert not included, 'include file should not be templated'
# else:
# assert list_results, "should find file"
list_files = set()
if isdir(dest_dir):
find_files(dest_dir,
[],
list_files,
)
if engine_name == 'base' and 'tmpfiles.d/0rougail.conf' in list_results:
list_results.remove('tmpfiles.d/0rougail.conf')
assert list_files == list_results, f'error with {test_dir}:'
for result in list_results:
template_file = join(dest_dir, 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')
with open(join(test_dir, 'result', result), 'r') as fh:
result_file = fh.read()
with open(template_file, 'r') as fh:
generated_file = fh.read()
assert result_file == generated_file, f'{template_file} content : \n{generated_file}\nexpected: \nresult_file\n'
if isdir(dest_dir):
rmtree(dest_dir)
if isdir(tmp_dir):
rmtree(tmp_dir)
@mark.asyncio
async def test_templates(test_dir):
for engine in ['base', 'systemd']:
not_file = join(template_dirs, test_dir, 'no_' + engine)
if isfile(not_file):
with raises(Exception) as err:
await templates(test_dir, 'base', '1', engine)
else:
await templates(test_dir, 'base', '1', engine)
@mark.asyncio @mark.asyncio
@ -119,10 +188,8 @@ async def test_template(test_dir):
for engine in ['base', 'systemd']: for engine in ['base', 'systemd']:
not_file = join(template_dirs, test_dir, 'no_' + engine) not_file = join(template_dirs, test_dir, 'no_' + engine)
if isfile(not_file): if isfile(not_file):
with raises(Exception) as err: continue
await template(test_dir, 'base', '1', engine) await templates(test_dir, 'base', '1', engine, only_one=True)
else:
await template(test_dir, 'base', '1', engine)
@mark.asyncio @mark.asyncio
@ -131,9 +198,9 @@ async def test_template_multi_1(test_dir):
not_file = join(template_dirs, test_dir, 'no_' + engine) not_file = join(template_dirs, test_dir, 'no_' + engine)
if isfile(not_file): if isfile(not_file):
with raises(Exception) as err: with raises(Exception) as err:
await template(test_dir, 'multi', '1', engine) await templates(test_dir, 'multi', '1', engine)
else: else:
await template(test_dir, 'multi', '1', engine) await templates(test_dir, 'multi', '1', engine)
@mark.asyncio @mark.asyncio
@ -142,6 +209,6 @@ async def test_template_multi_2(test_dir):
not_file = join(template_dirs, test_dir, 'no_' + engine) not_file = join(template_dirs, test_dir, 'no_' + engine)
if isfile(not_file): if isfile(not_file):
with raises(Exception) as err: with raises(Exception) as err:
await template(test_dir, 'multi', '1', engine) await templates(test_dir, 'multi', '1', engine)
else: else:
await template(test_dir, 'multi', '1', engine) await templates(test_dir, 'multi', '1', engine)