forked from stove/risotto
235 lines
9 KiB
Python
Executable file
235 lines
9 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
from asyncio import run
|
|
from tabulate import tabulate
|
|
from argparse import ArgumentParser
|
|
|
|
from rougail.utils import normalize_family
|
|
from tiramisu.error import PropertiesOptionError
|
|
from risotto.machine import load, remove_cache, ROUGAIL_NAMESPACE
|
|
|
|
|
|
HIDE_SECRET = True
|
|
|
|
|
|
def list_to_string(lst):
|
|
if isinstance(lst, list):
|
|
return "\n".join([str(val) for val in lst])
|
|
return lst
|
|
|
|
|
|
async def get_files_subelements(type_name, element, files_subelement, files_cols):
|
|
data = {}
|
|
if not await element.option('activate').value.get():
|
|
return data
|
|
for subelement in files_subelement.values():
|
|
if subelement['type'] == 'subelement':
|
|
try:
|
|
value = list_to_string(await element.option(subelement['key']).value.get())
|
|
# FIXME except AttributeError:
|
|
except Exception:
|
|
value = ''
|
|
elif subelement['type'] == 'information':
|
|
value = await element.information.get(subelement['key'], '')
|
|
elif subelement['type'] == 'none':
|
|
value = subelement['value']
|
|
else:
|
|
raise Exception('unknown subelement')
|
|
if value != '':
|
|
files_cols.add(subelement['key'])
|
|
data[subelement['key']] = value
|
|
if type_name == 'overrides':
|
|
data['name'] = f'/systemd/system/{data["source"]}.d/rougail.conf'
|
|
if not data['engine']:
|
|
data['engine'] = 'none'
|
|
elif not data['engine']:
|
|
data['engine'] = 'cheetah'
|
|
return data
|
|
|
|
|
|
async def services(config, values):
|
|
files_subelement = {'Source': {'key': 'source', 'type': 'information'},
|
|
'Nom': {'key': 'name', 'type': 'subelement'},
|
|
'Variable': {'key': 'variable', 'type': 'subelement'},
|
|
'Propriétaire': {'key': 'owner', 'type': 'subelement'},
|
|
'Groupe': {'key': 'group', 'type': 'subelement'},
|
|
'Mode': {'key': 'mode', 'type': 'subelement'},
|
|
'Moteur': {'key': 'engine', 'type': 'information'},
|
|
}
|
|
disabled_services = []
|
|
for service in await config.option.list(type="all"):
|
|
doc = await service.option.doc()
|
|
files_lst = []
|
|
files_cols = set()
|
|
if not await service.option('manage').value.get():
|
|
doc += " - unmanaged"
|
|
if not await service.option('activate').value.get():
|
|
disabled_services.append([doc])
|
|
else:
|
|
for type in await service.list(type="all"):
|
|
type_name = await type.option.doc()
|
|
if type_name in ['files', 'overrides']:
|
|
for element in await type.list(type="all"):
|
|
data = await get_files_subelements(type_name, element, files_subelement, files_cols)
|
|
if data:
|
|
files_lst.append(data)
|
|
elif type_name == 'manage':
|
|
pass
|
|
elif type_name == 'activate':
|
|
if not await type.value.get():
|
|
doc += " - unactivated"
|
|
else:
|
|
print("FIXME " + type_name)
|
|
if files_lst:
|
|
keys = [key for key, val in files_subelement.items() if val['key'] in files_cols]
|
|
values[doc] = {'keys': keys, 'lst': []}
|
|
for lst in files_lst:
|
|
values[doc]['lst'].append([val for key, val in lst.items() if key in files_cols])
|
|
if disabled_services:
|
|
values["Services désactivés"] = {'keys': ['Nom'], 'lst': disabled_services}
|
|
|
|
|
|
async def table_leader(config, read_only):
|
|
keys = ['Description']
|
|
if read_only:
|
|
keys.append('Cachée')
|
|
leadership_lst = await config.list(type="all")
|
|
leader = leadership_lst.pop(0)
|
|
leader_owner = await leader.owner.get()
|
|
follower_names = [await follower.option.name() for follower in leadership_lst]
|
|
doc = await leader.option.doc()
|
|
properties = await leader.property.get()
|
|
if 'mandatory' in properties:
|
|
doc += '*'
|
|
name = await leader.option.name()
|
|
lst = [[f'{doc} ({name})']]
|
|
if read_only:
|
|
if 'hidden' in properties:
|
|
hidden = 'oui'
|
|
else:
|
|
hidden = ''
|
|
lst[0].append(hidden)
|
|
for idx, leader_value in enumerate(await leader.value.get()):
|
|
keys.append(f'Valeur {idx}')
|
|
keys.append(f'Utilisateur {idx}')
|
|
lst[0].append(leader_value)
|
|
lst[0].append(leader_owner)
|
|
for follower_idx, follower_name in enumerate(follower_names):
|
|
follower_option = config.option(follower_name, idx)
|
|
if idx == 0:
|
|
doc = await follower_option.option.doc()
|
|
properties = await follower_option.property.get()
|
|
if 'mandatory' in properties:
|
|
doc += '*'
|
|
name = await follower_option.option.name()
|
|
lst.append([f'{doc} ({name})'])
|
|
if read_only:
|
|
if 'hidden' in properties:
|
|
hidden = 'oui'
|
|
else:
|
|
hidden = ''
|
|
lst[-1].append(hidden)
|
|
try:
|
|
lst[follower_idx + 1].append(list_to_string(await follower_option.value.get()))
|
|
lst[follower_idx + 1].append(await follower_option.owner.get())
|
|
except PropertiesOptionError:
|
|
pass
|
|
# leader = next leader_iter
|
|
# if master_values is None:
|
|
# master_values = await subconfig.value.get()
|
|
return {'keys': keys, 'lst': lst}
|
|
|
|
|
|
async def table(config, prefix_len, values, read_only):
|
|
lst = []
|
|
for subconfig in await config.option.list(type="all"):
|
|
# prefix = prefix_len * 2 * ' '
|
|
# if await subconfig.option.isoptiondescription():
|
|
# prefix += '=>'
|
|
# else:
|
|
# prefix += '-'
|
|
# display_str = f'{prefix} {description}'
|
|
# if name != description:
|
|
# display_str = f'{display_str} ({name})'
|
|
name = await subconfig.option.name()
|
|
doc = await subconfig.option.doc()
|
|
if prefix_len == 0 and ROUGAIL_NAMESPACE != name:
|
|
doc = doc.capitalize()
|
|
if prefix_len == 0 and name == 'services':
|
|
values['Services'] = {}
|
|
await services(subconfig, values['Services'])
|
|
elif await subconfig.option.isoptiondescription():
|
|
od_name = f'{doc} ({(await subconfig.option.path()).split(".", 1)[1]})'
|
|
values[od_name] = None
|
|
if await subconfig.option.isleadership():
|
|
values[od_name] = await table_leader(subconfig, read_only)
|
|
else:
|
|
values[od_name] = await table(subconfig, prefix_len + 1, values, read_only)
|
|
else:
|
|
value = list_to_string(await subconfig.value.get())
|
|
doc = await subconfig.option.doc()
|
|
properties = await subconfig.property.get()
|
|
if 'mandatory' in properties:
|
|
doc += '*'
|
|
name = await subconfig.option.name()
|
|
lst.append([f'{doc} ({name})', value])
|
|
if read_only:
|
|
if 'hidden' in properties:
|
|
hidden = 'oui'
|
|
else:
|
|
hidden = ''
|
|
lst[-1].append(hidden)
|
|
lst[-1].append(await subconfig.owner.get())
|
|
keys = ['Description', 'Valeur']
|
|
if read_only:
|
|
keys.append('Cachée')
|
|
keys.append('Utilisateur')
|
|
return {'keys': keys, 'lst': lst}
|
|
|
|
|
|
async def main():
|
|
parser = ArgumentParser()
|
|
parser.add_argument('server_name')
|
|
parser.add_argument('--read_only', action='store_true')
|
|
parser.add_argument('--nocache', action='store_true')
|
|
args = parser.parse_args()
|
|
if args.nocache:
|
|
remove_cache()
|
|
|
|
values = {}
|
|
server_name = args.server_name
|
|
config = await load(hide_secret=HIDE_SECRET,
|
|
original_display_name=True,
|
|
valid_mandatories=args.read_only,
|
|
)
|
|
if not args.read_only:
|
|
await config.property.read_write()
|
|
root_option = config.option(normalize_family(server_name))
|
|
try:
|
|
await root_option.option.get()
|
|
except AttributeError:
|
|
exit(f'Unable to find {server_name} configuration: {[await o.option.description() for o in await config.option.list(type="optiondescription")]}')
|
|
await table(root_option, 0, values, args.read_only)
|
|
for title, dico in values.items():
|
|
if title == 'Services':
|
|
if not dico:
|
|
continue
|
|
print()
|
|
print(title)
|
|
print('=' * len(title))
|
|
print()
|
|
for subtitle, dic in dico.items():
|
|
print()
|
|
print(' ' + subtitle)
|
|
print(' ' + '-' * len(subtitle))
|
|
print()
|
|
print(tabulate(dic['lst'], headers=dic['keys'], tablefmt="fancy_grid"))
|
|
elif dico['lst']:
|
|
print()
|
|
print(title)
|
|
print('=' * len(title))
|
|
print()
|
|
print(tabulate(dico['lst'], headers=dico['keys'], tablefmt="fancy_grid"))
|
|
|
|
|
|
run(main())
|