rougail-output-ansible/tests/test_load.py

407 lines
11 KiB
Python
Raw Normal View History

2026-02-21 21:31:34 +01:00
import os
2024-12-02 20:22:27 +01:00
from pytest import fixture # , raises
from pathlib import Path
from yaml import safe_load
2024-12-02 20:22:27 +01:00
from rougail import Rougail
2026-02-21 21:31:34 +01:00
from rougail.user_data import mandatories
2024-12-02 20:22:27 +01:00
from rougail.output_ansible import RougailOutputAnsible as RougailOutput
from rougail.user_data_yaml import RougailUserDataYaml
2024-12-02 20:22:27 +01:00
from rougail_tests.utils import get_structures_list, get_rougail_config, get_values_for_config
2026-02-21 21:31:34 +01:00
WITH_DONE = False
# WITH_DONE = True
HERE = Path(__file__).parent
2024-12-02 20:22:27 +01:00
EXT = 'json'
2026-02-21 21:31:34 +01:00
os.environ['COLUMNS'] = '80'
2024-12-02 20:22:27 +01:00
2026-01-21 08:55:24 +01:00
excludes = [
# '04_5disabled_calculation_variable11',
2024-12-02 20:22:27 +01:00
# '60_5family_dynamic_variable_outside_sub_suffix',
2026-01-21 08:55:24 +01:00
]
2024-12-02 20:22:27 +01:00
2026-02-21 21:31:34 +01:00
if WITH_DONE:
test_ok = get_structures_list(excludes, HERE)
else:
test_ok = get_structures_list(excludes)
2026-05-04 12:17:56 +02:00
# test_ok = [Path('../rougail-tests/structures/00_1empty_variable')]
2024-12-02 20:22:27 +01:00
def idfn(fixture_value):
return fixture_value.name
@fixture(scope="module", params=test_ok, ids=idfn)
def test_dir(request):
return request.param
2025-09-22 14:29:45 +02:00
def _test_structural_files(test_dir, namespace, ext, *, read_write=True, mandatory=False, do_calc=True):
2026-01-14 14:25:35 +01:00
for output in ['inventory', 'doc']:
rougailconfig = get_rougail_config(test_dir, namespace)
if not rougailconfig:
continue
##################################
rougailconfig['step.output'] = 'ansible'
2026-02-21 21:31:34 +01:00
# rougailconfig["json.mandatory"] = mandatory
2026-01-14 14:25:35 +01:00
if output == 'inventory':
extra_namespaces = rougailconfig["extra_namespaces"]
2026-02-21 21:31:34 +01:00
extra_namespaces["hosts"] = [str(HERE / "hosts")]
2026-01-14 14:25:35 +01:00
rougailconfig['extra_namespaces'] = extra_namespaces
##################################
dir_name = 'test'
if namespace:
dir_name += '_namespace'
elif (test_dir / 'force_namespace').is_file():
return
##################################
if read_write:
dir_name += '_read_write'
2025-04-21 21:23:58 +02:00
if mandatory:
2026-01-14 14:25:35 +01:00
dir_name += '_mandatory'
if not do_calc:
dir_name += '_errors'
2026-02-21 21:31:34 +01:00
if output == 'inventory':
dirname = 'results'
else:
dirname = 'results-doc'
ext = 'sh'
output_file = HERE / dirname / dir_name / (test_dir.name + "." + ext)
2026-01-14 14:25:35 +01:00
##################################
rougail = Rougail(rougailconfig)
config = rougail.run()
config.information.set("description_type", "path_and_description")
##################################
if do_calc and (mandatory or not read_write):
if mandatory:
get_values_for_config(config, exclude_namespace="hosts")
else:
get_values_for_config(config, level="mandatories", exclude_namespace="hosts")
##################################
if read_write:
config.property.read_write()
2025-04-21 21:23:58 +02:00
else:
2026-01-14 14:25:35 +01:00
config.property.read_only()
2026-02-21 21:31:34 +01:00
errors = []
if mandatory:
mandatories(config, errors)
if output != 'inventory':
2026-01-14 14:25:35 +01:00
subconfig = config.list()
if len(subconfig) != 1 or not subconfig[0].isoptiondescription():
continue
rougailconfig['ansible.output'] = output
2026-05-04 12:17:56 +02:00
if output == 'doc':
rougailconfig["ansible.doc.project_name"] = "rougail"
rougailconfig["ansible.doc.author"] = "rougail"
2026-02-21 21:31:34 +01:00
generated_output = RougailOutput(config, rougailconfig=rougailconfig, user_data_errors=errors).run()[1]
2026-01-14 14:25:35 +01:00
if not output_file.is_file():
if not output_file.parent.is_dir():
output_file.parent.mkdir(parents=True)
with output_file.open('w') as outfh:
outfh.write(generated_output)
with output_file.open() as outfh:
attented_output = outfh.read()
assert generated_output == attented_output, f'filename {output_file}'
2026-02-21 21:31:34 +01:00
if WITH_DONE:
with (HERE / (test_dir.name + ".DONE")).open("w") as fh:
fh.write('')
2024-12-02 20:22:27 +01:00
# do not test without namespace, ansible needs namespaces
2025-09-22 14:29:45 +02:00
def test_structural_files_ansible_namespace(test_dir):
_test_structural_files(test_dir, True, EXT)
2024-12-02 20:22:27 +01:00
2025-09-22 14:29:45 +02:00
def test_structural_files_ansible_namespace_errors(test_dir):
_test_structural_files(test_dir, True, EXT, do_calc=False, mandatory=True)
2024-12-02 20:22:27 +01:00
2025-09-22 14:29:45 +02:00
def test_structural_files_ansible_namespace_read_only(test_dir):
_test_structural_files(test_dir, True, EXT, read_write=False)
2024-12-02 20:22:27 +01:00
2025-09-22 14:29:45 +02:00
def test_structural_files_ansible_namespace_mandatory(test_dir):
_test_structural_files(test_dir, True, EXT, mandatory=True)
2024-12-02 20:22:27 +01:00
2025-09-22 14:29:45 +02:00
def test_structural_files_ansible_namespace_mandatory_read_only(test_dir):
_test_structural_files(test_dir, True, EXT, read_write=False, mandatory=True)
def test_warnings():
rougailconfig = get_rougail_config(Path('tests/warnings/structures'), True)
##################################
rougailconfig['step.output'] = 'ansible'
rougailconfig['step.user_data'] = ['yaml']
rougailconfig['yaml.filename'] = ['tests/warnings/yaml/config.yml']
2025-09-22 14:29:45 +02:00
extra_namespaces = rougailconfig["extra_namespaces"]
2026-02-21 21:31:34 +01:00
extra_namespaces["hosts"] = [str(HERE / "hosts")]
2025-09-22 14:29:45 +02:00
rougailconfig['extra_namespaces'] = extra_namespaces
##################################
rougail = Rougail(rougailconfig)
config = rougail.run()
generated_user_data = RougailUserDataYaml(config, rougailconfig=rougailconfig).run()
2025-12-29 19:29:11 +01:00
err_warn = rougail.user_data(generated_user_data)
output = RougailOutput(
config=config,
rougailconfig=rougailconfig,
user_data_errors=err_warn["errors"],
user_data_warnings=err_warn["warnings"],
)
ret = output.run()
assert ret[0] is True
assert safe_load(ret[1]) == {
"_meta": {
"hostvars": {
"localhost": {
"_warnings": [
2026-01-21 08:55:24 +01:00
"rougail: variable or family \"an_unknown_var\" does not exist so cannot load \"rougail.an_unknown_var\", it will be ignored when loading from the YAML file \"tests/warnings/yaml/config.yml\""
]
},
"GROUP1_01": {
"ansible_host": "group1.net",
"rougail": {
"a_var": "a_value"
}
},
"GROUP2_01": {
"ansible_host": "group2.net",
2025-09-10 17:42:09 +02:00
'rougail': {
'a_var': 'a_value',
},
},
'GROUP2_02': {
'ansible_host': 'group3.net',
'rougail': {
'a_var': 'a_value',
},
},
'group4.net': {
'ansible_host': 'group4.net',
'rougail': {
'a_var': 'a_value',
},
},
'group5.net': {
'ansible_host': 'group5.net',
"rougail": {
"a_var": "a_value"
}
}
}
},
"ungrouped": {
"hosts": [
"localhost"
]
},
"group1": {
"hosts": [
"GROUP1_01"
]
},
"group2": {
"hosts": [
2025-09-10 17:42:09 +02:00
"GROUP2_01",
'GROUP2_02'
]
},
2025-09-10 17:42:09 +02:00
'group3': {
'hosts': [
'group4.net',
'group5.net',
]
},
"groups": {
"children": [
"group1",
"group2"
]
}
}
def test_no_warnings():
rougailconfig = get_rougail_config(Path('tests/warnings/structures'), True)
##################################
rougailconfig['step.output'] = 'ansible'
2026-01-14 14:25:35 +01:00
rougailconfig['ansible.inventory.export_warnings'] = False
rougailconfig['step.user_data'] = ['yaml']
rougailconfig['yaml.filename'] = ['tests/warnings/yaml/config.yml']
2025-09-22 14:29:45 +02:00
extra_namespaces = rougailconfig["extra_namespaces"]
2026-02-21 21:31:34 +01:00
extra_namespaces["hosts"] = [str(HERE / "hosts")]
2025-09-22 14:29:45 +02:00
rougailconfig['extra_namespaces'] = extra_namespaces
##################################
rougail = Rougail(rougailconfig)
config = rougail.run()
generated_user_data = RougailUserDataYaml(config, rougailconfig=rougailconfig).run()
2025-12-29 19:29:11 +01:00
err_warn = rougail.user_data(generated_user_data)
output = RougailOutput(
config=config,
rougailconfig=rougailconfig,
user_data_errors=err_warn["errors"],
user_data_warnings=err_warn["warnings"],
)
ret = output.run()
assert ret[0] is True
assert safe_load(ret[1]) == {
2026-01-09 08:46:16 +01:00
"_meta": {
"hostvars": {
"GROUP1_01": {
"ansible_host": "group1.net",
"rougail": {
"a_var": "a_value"
}
},
"GROUP2_01": {
"ansible_host": "group2.net",
'rougail': {
'a_var': 'a_value',
},
},
'GROUP2_02': {
'ansible_host': 'group3.net',
'rougail': {
'a_var': 'a_value',
},
},
'group4.net': {
'ansible_host': 'group4.net',
'rougail': {
'a_var': 'a_value',
},
},
'group5.net': {
'ansible_host': 'group5.net',
"rougail": {
"a_var": "a_value"
}
}
}
},
'group1': {
'hosts': [
'GROUP1_01',
],
},
'group2': {
'hosts': [
'GROUP2_01',
'GROUP2_02',
],
},
'group3': {
'hosts': [
'group4.net',
'group5.net',
],
},
'groups': {
'children': [
'group1',
'group2',
],
}
}
def test_host_with_vars():
rougailconfig = get_rougail_config(Path('tests/warnings/structures'), True)
##################################
rougailconfig['step.output'] = 'ansible'
2026-01-14 14:25:35 +01:00
rougailconfig['ansible.inventory.export_warnings'] = False
2026-01-09 08:46:16 +01:00
rougailconfig['step.user_data'] = ['yaml']
rougailconfig['yaml.filename'] = ['tests/warnings/yaml/config.yml']
extra_namespaces = rougailconfig["extra_namespaces"]
2026-02-21 21:31:34 +01:00
extra_namespaces["hosts"] = [str(HERE / "hosts-with-vars")]
2026-01-09 08:46:16 +01:00
rougailconfig['extra_namespaces'] = extra_namespaces
##################################
rougail = Rougail(rougailconfig)
config = rougail.run()
generated_user_data = RougailUserDataYaml(config, rougailconfig=rougailconfig).run()
err_warn = rougail.user_data(generated_user_data)
output = RougailOutput(
config=config,
rougailconfig=rougailconfig,
user_data_errors=err_warn["errors"],
user_data_warnings=err_warn["warnings"],
)
ret = output.run()
assert ret[0] is True
assert safe_load(ret[1]) == {
"_meta": {
"hostvars": {
"GROUP1_01": {
"ansible_host": "group1.net",
"rougail": {
"a_var": "a_value"
}
},
"GROUP2_01": {
2026-01-10 17:04:47 +01:00
'a_family': {
'with_a_variable': 1,
},
'added_var1': True,
'added_var2': True,
"ansible_host": "group2.net",
2025-09-10 17:42:09 +02:00
'rougail': {
'a_var': 'a_value',
},
},
'GROUP2_02': {
2026-01-10 17:04:47 +01:00
'a_family': {
'with_a_variable': 1,
},
'added_var1': True,
2025-09-10 17:42:09 +02:00
'ansible_host': 'group3.net',
'rougail': {
'a_var': 'a_value',
},
},
'group4.net': {
'ansible_host': 'group4.net',
'rougail': {
'a_var': 'a_value',
},
},
'group5.net': {
'ansible_host': 'group5.net',
"rougail": {
"a_var": "a_value"
}
}
}
},
2025-09-10 17:42:09 +02:00
'group1': {
'hosts': [
'GROUP1_01',
],
},
2025-09-10 17:42:09 +02:00
'group2': {
'hosts': [
'GROUP2_01',
'GROUP2_02',
],
},
2025-09-10 17:42:09 +02:00
'group3': {
'hosts': [
'group4.net',
'group5.net',
],
},
2025-09-10 17:42:09 +02:00
'groups': {
'children': [
'group1',
'group2',
],
}
}