forked from stove/risotto
only one config
This commit is contained in:
parent
231125be0c
commit
e3bca44f3a
7 changed files with 622 additions and 615 deletions
106
bootstrap.py
106
bootstrap.py
|
@ -6,9 +6,10 @@ from os.path import isdir, join
|
|||
from shutil import rmtree
|
||||
from copy import copy
|
||||
|
||||
from risotto.utils import CONFIGS, RISOTTO_CONFIG, SERVERS
|
||||
from risotto.image import load
|
||||
from risotto.machine import templates
|
||||
from risotto.utils import RISOTTO_CONFIG, SERVERS
|
||||
#from risotto.image import load
|
||||
from risotto.machine import templates, load, ROUGAIL_NAMESPACE
|
||||
from rougail.utils import normalize_family
|
||||
|
||||
|
||||
INSTALL_DIR = RISOTTO_CONFIG['directories']['dest']
|
||||
|
@ -34,53 +35,84 @@ async def main():
|
|||
if isdir(INSTALL_DIR):
|
||||
rmtree(INSTALL_DIR)
|
||||
makedirs(INSTALL_DIR)
|
||||
module_infos = await load(display_name=tiramisu_display_name, clean_directories=True, copy_manual_dir=True)
|
||||
try:
|
||||
module_infos, rougailconfig, config = await load(display_name=tiramisu_display_name,
|
||||
clean_directories=True,
|
||||
copy_manual_dir=True,
|
||||
copy_tests=True,
|
||||
)
|
||||
except Exception as err:
|
||||
# import traceback
|
||||
# traceback.print_exc()
|
||||
print(err)
|
||||
exit(1)
|
||||
modules_done = []
|
||||
for server_name in SERVERS:
|
||||
module_name = CONFIGS[server_name]['module_name']
|
||||
add_srv = CONFIGS[server_name]['add_srv']
|
||||
cfg = CONFIGS[server_name]['templates_informations']
|
||||
cfg['tmp_dir'] = 'tmp'
|
||||
cfg['destinations_dir'] = join(INSTALL_DIR, module_name, CONFIG_DEST_DIR, server_name)
|
||||
module_name = SERVERS[server_name]['module']
|
||||
module_info = module_infos[module_name]
|
||||
subconfig = config.option(normalize_family(server_name))
|
||||
try:
|
||||
add_srv = await subconfig.option('machine.add_srv').value.get()
|
||||
except AttributeError:
|
||||
add_srv = False
|
||||
rougailconfig['tmp_dir'] = 'tmp'
|
||||
rougailconfig['destinations_dir'] = join(INSTALL_DIR, module_name, CONFIG_DEST_DIR, server_name)
|
||||
rougailconfig['templates_dir'] = module_info['infos'].templates_dir
|
||||
if module_name == 'host':
|
||||
tmpfile = await subconfig.option(f'{ROUGAIL_NAMESPACE}.host_install_dir').value.get()
|
||||
rougailconfig['tmpfile_dest_dir'] = f'{tmpfile}/host/configurations/{server_name}'
|
||||
rougailconfig['default_systemd_directory'] = '/usr/local/lib/systemd'
|
||||
else:
|
||||
rougailconfig['tmpfile_dest_dir'] = '/usr/local/lib'
|
||||
rougailconfig['default_systemd_directory'] = '/systemd'
|
||||
# cfg['templates_dir'] = module_info['infos'].templates_dir
|
||||
if isdir('tmp'):
|
||||
rmtree('tmp')
|
||||
makedirs(cfg['tmp_dir'])
|
||||
makedirs(cfg['destinations_dir'])
|
||||
makedirs(rougailconfig['tmp_dir'])
|
||||
makedirs(rougailconfig['destinations_dir'])
|
||||
if add_srv:
|
||||
srv = join(INSTALL_DIR, SRV_DEST_DIR, server_name)
|
||||
else:
|
||||
srv = None
|
||||
await templates(server_name, **CONFIGS[server_name], srv=srv)
|
||||
for server_name in SERVERS:
|
||||
config = CONFIGS[server_name]['config']
|
||||
await templates(server_name,
|
||||
subconfig,
|
||||
rougailconfig,
|
||||
srv=srv,
|
||||
)
|
||||
#
|
||||
await config.property.read_write()
|
||||
try:
|
||||
# pass
|
||||
await config.option('general.hide_secret').value.set(True)
|
||||
except AttributeError:
|
||||
# if rougail.general.hide_secret not exists
|
||||
await subconfig.option('general.hide_secret').value.set(True)
|
||||
except AttributeError as err:
|
||||
# print(err)
|
||||
pass
|
||||
await config.property.read_only()
|
||||
for server_name in SERVERS:
|
||||
config = CONFIGS[server_name]['config']
|
||||
await config.value.dict()
|
||||
for server_name in SERVERS:
|
||||
module_name = CONFIGS[server_name]['module_name']
|
||||
destinations_dir = join(INSTALL_DIR, module_name, CONFIG_DIFF_DIR, server_name)
|
||||
makedirs(destinations_dir)
|
||||
CONFIGS[server_name]['templates_informations']['destinations_dir'] = destinations_dir
|
||||
await templates(server_name, **CONFIGS[server_name])
|
||||
for module_name, cfg in module_infos.items():
|
||||
with open(join(INSTALL_DIR, module_name, 'install_machines'), 'w') as fh:
|
||||
for idx, server_name in enumerate(cfg['infos'].servers):
|
||||
if not idx:
|
||||
destinations_dir = join(INSTALL_DIR, module_name, CONFIG_ORI_DIR)
|
||||
makedirs(destinations_dir)
|
||||
CONFIGS[server_name]['templates_informations']['destinations_dir'] = destinations_dir
|
||||
rougailconfig['destinations_dir'] = join(INSTALL_DIR, module_name, CONFIG_DIFF_DIR, server_name)
|
||||
rmtree('tmp')
|
||||
makedirs(rougailconfig['tmp_dir'])
|
||||
makedirs(rougailconfig['destinations_dir'])
|
||||
await templates(server_name,
|
||||
**CONFIGS[server_name],
|
||||
subconfig,
|
||||
rougailconfig,
|
||||
)
|
||||
await config.property.read_write()
|
||||
try:
|
||||
await subconfig.option('general.hide_secret').value.set(False)
|
||||
except AttributeError as err:
|
||||
pass
|
||||
await config.property.read_only()
|
||||
#
|
||||
if module_name not in modules_done:
|
||||
rougailconfig['destinations_dir'] = join(INSTALL_DIR, module_name, CONFIG_ORI_DIR)
|
||||
rmtree('tmp')
|
||||
makedirs(rougailconfig['tmp_dir'])
|
||||
makedirs(rougailconfig['destinations_dir'])
|
||||
await templates(server_name,
|
||||
subconfig,
|
||||
rougailconfig,
|
||||
just_copy=True,
|
||||
)
|
||||
modules_done.append(module_name)
|
||||
with open(join(INSTALL_DIR, module_name, 'install_machines'), 'w') as fh:
|
||||
fh.write(f'./install_machine {module_name} {server_name}\n')
|
||||
|
||||
|
||||
run(main())
|
||||
|
|
21
funcs.py
21
funcs.py
|
@ -5,7 +5,7 @@ from secrets import token_urlsafe as _token_urlsafe
|
|||
|
||||
from rougail.utils import normalize_family
|
||||
|
||||
from risotto.utils import multi_function, DOMAINS, ZONES, load_zones, load_zones_server, load_domains, ZONES_SERVER
|
||||
from risotto.utils import multi_function, DOMAINS, ZONES, load_zones, load_zones_server, load_domains, SERVERS_JSON
|
||||
from risotto.x509 import gen_cert as _x509_gen_cert, gen_ca as _x509_gen_ca, gen_pub as _x509_gen_pub, has_pub as _x509_has_pub
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ def get_chain(authority_cn: str,
|
|||
):
|
||||
if hide:
|
||||
return "XXXXX"
|
||||
if not authority_name or authority_name is None:
|
||||
if not authority_cn or not authority_name or authority_name is None:
|
||||
if isinstance(authority_name, list):
|
||||
return []
|
||||
return
|
||||
|
@ -142,7 +142,7 @@ def get_internal_zones() -> List[str]:
|
|||
def get_zones_info(type: str) -> str:
|
||||
load_zones_server()
|
||||
ret = []
|
||||
for data in ZONES_SERVER['zones'].values():
|
||||
for data in SERVERS_JSON['zones'].values():
|
||||
ret.append(data[type])
|
||||
return ret
|
||||
|
||||
|
@ -160,19 +160,4 @@ def get_internal_zone_information(zone: str,
|
|||
return ZONES[zone]['gateway'] + '/' + ZONES[zone]['network'].split('/')[-1]
|
||||
return ZONES[zone][info]
|
||||
|
||||
|
||||
def get_internal_info_in_zone(zone: str,
|
||||
auto: bool,
|
||||
type: str,
|
||||
index: int=None,
|
||||
) -> List[str]:
|
||||
if not auto:
|
||||
return
|
||||
for domain_name, domain in DOMAINS.items():
|
||||
if zone == domain_name:
|
||||
if type == 'host':
|
||||
return list(domain[0])
|
||||
else:
|
||||
return domain[1][index]
|
||||
|
||||
# =============================================================
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
from shutil import copy2, copytree, rmtree
|
||||
from os import listdir, makedirs
|
||||
from os.path import join, isdir, isfile
|
||||
from os.path import join, isdir, isfile, dirname
|
||||
from yaml import load as yaml_load, SafeLoader
|
||||
from json import load as json_load
|
||||
|
||||
from .utils import CONFIGS, RISOTTO_CONFIG, SERVERS, ZONES_SERVER, value_pprint
|
||||
from .machine import load_machine_config
|
||||
#
|
||||
from rougail import RougailConfig # , RougailConvert
|
||||
#
|
||||
from .utils import RISOTTO_CONFIG, SERVERS, MULTI_FUNCTIONS
|
||||
|
||||
|
||||
FUNCTIONS = 'funcs.py'
|
||||
FUNCTIONS_FILE = 'funcs.py'
|
||||
|
||||
|
||||
class ModuleCfg():
|
||||
def __init__(self):
|
||||
def __init__(self, module_name):
|
||||
self.module_name = module_name
|
||||
self.dictionaries_dir = []
|
||||
self.modules = []
|
||||
self.functions_file = [FUNCTIONS]
|
||||
self.functions_file = [FUNCTIONS_FILE]
|
||||
self.templates_dir = []
|
||||
self.extra_dictionaries = {}
|
||||
self.servers = []
|
||||
|
||||
def __repr__(self):
|
||||
return str(vars(self))
|
||||
|
||||
|
||||
def list_applications() -> dict:
|
||||
"""
|
||||
|
@ -40,8 +45,6 @@ def list_applications() -> dict:
|
|||
def applicationservice_copy(src_file: str,
|
||||
dst_file: str,
|
||||
copy_if_not_exists: bool,
|
||||
manual_dir: str,
|
||||
filename: str,
|
||||
) -> None:
|
||||
if isdir(src_file):
|
||||
if not isdir(dst_file):
|
||||
|
@ -55,12 +58,13 @@ def applicationservice_copy(src_file: str,
|
|||
else:
|
||||
copytree(src, dst)
|
||||
elif not copy_if_not_exists or not isfile(dst_file):
|
||||
src = join(manual_dir, filename)
|
||||
dst = dst_file
|
||||
if isfile(src):
|
||||
copy2(src, dst)
|
||||
dst = dirname(dst_file)
|
||||
if not isdir(dst):
|
||||
makedirs(dst)
|
||||
if isfile(src_file):
|
||||
copy2(src_file, dst_file)
|
||||
else:
|
||||
copytree(src, dst)
|
||||
copytree(src_file, dst_file)
|
||||
|
||||
|
||||
def load_applicationservice_cfg(appname: str,
|
||||
|
@ -68,6 +72,7 @@ def load_applicationservice_cfg(appname: str,
|
|||
install_dir: str,
|
||||
cfg: ModuleCfg,
|
||||
copy_manual_dir: bool,
|
||||
copy_tests: bool,
|
||||
) -> None:
|
||||
cfg.modules.append(appname)
|
||||
# dictionaries
|
||||
|
@ -109,8 +114,16 @@ def load_applicationservice_cfg(appname: str,
|
|||
applicationservice_copy(src_file,
|
||||
dst_file,
|
||||
copy_if_not_exists,
|
||||
manual_dir,
|
||||
filename,
|
||||
)
|
||||
if copy_tests:
|
||||
tests_dir = join(as_dir, 'tests')
|
||||
if isdir(tests_dir):
|
||||
for filename in listdir(tests_dir):
|
||||
src_file = join(tests_dir, filename)
|
||||
dst_file = join(install_dir, 'tests', filename)
|
||||
applicationservice_copy(src_file,
|
||||
dst_file,
|
||||
False,
|
||||
)
|
||||
|
||||
|
||||
|
@ -120,10 +133,12 @@ def load_applicationservice(appname: str,
|
|||
cfg: ModuleCfg,
|
||||
applications: dict,
|
||||
copy_manual_dir: bool,
|
||||
copy_tests: bool,
|
||||
providers: dict,
|
||||
suppliers: dict,
|
||||
) -> None:
|
||||
if appname not in applications:
|
||||
raise Exception(f'cannot find application dependency "{appname}" in application "{module_name}"')
|
||||
raise Exception(f'cannot find application dependency "{appname}"')
|
||||
as_dir = applications[appname]
|
||||
applicationservice_file = join(as_dir, 'applicationservice.yml')
|
||||
if not isfile(applicationservice_file):
|
||||
|
@ -133,6 +148,7 @@ def load_applicationservice(appname: str,
|
|||
install_dir,
|
||||
cfg,
|
||||
copy_manual_dir,
|
||||
copy_tests,
|
||||
)
|
||||
added.append(appname)
|
||||
with open(applicationservice_file) as yaml:
|
||||
|
@ -142,6 +158,11 @@ def load_applicationservice(appname: str,
|
|||
providers.setdefault(provider, [])
|
||||
if appname not in providers[provider]:
|
||||
providers[provider].append(appname)
|
||||
supplier = app.get('supplier')
|
||||
if supplier:
|
||||
suppliers.setdefault(supplier, [])
|
||||
if appname not in suppliers[supplier]:
|
||||
suppliers[supplier].append(appname)
|
||||
for xml in app.get('depends', []):
|
||||
if xml in added:
|
||||
continue
|
||||
|
@ -151,17 +172,22 @@ def load_applicationservice(appname: str,
|
|||
cfg,
|
||||
applications,
|
||||
copy_manual_dir,
|
||||
copy_tests,
|
||||
providers,
|
||||
suppliers,
|
||||
)
|
||||
|
||||
|
||||
def load_image_informations(install_dir: str,
|
||||
def load_image_informations(module_name: str,
|
||||
install_dir: str,
|
||||
datas: dict,
|
||||
applications: dict,
|
||||
copy_manual_dir: bool,
|
||||
copy_tests: bool,
|
||||
providers: dict,
|
||||
suppliers: dict,
|
||||
) -> ModuleCfg:
|
||||
cfg = ModuleCfg()
|
||||
cfg = ModuleCfg(module_name)
|
||||
added = []
|
||||
for applicationservice in datas['applicationservices']:
|
||||
load_applicationservice(applicationservice,
|
||||
|
@ -170,53 +196,35 @@ def load_image_informations(install_dir: str,
|
|||
cfg,
|
||||
applications,
|
||||
copy_manual_dir,
|
||||
copy_tests,
|
||||
providers,
|
||||
suppliers,
|
||||
)
|
||||
return cfg
|
||||
|
||||
|
||||
async def load_informations(server_name, datas, config):
|
||||
await config.information.set('server_name', server_name)
|
||||
if 'informations' not in datas:
|
||||
return
|
||||
for information, value in datas['informations'].items():
|
||||
await config.information.set(information, value)
|
||||
if 'extra_domainnames' in datas['informations']:
|
||||
for idx, extra_domainname in enumerate(datas['informations']['extra_domainnames']):
|
||||
if extra_domainname in CONFIGS:
|
||||
raise Exception(f'server "{server_name}" is duplicate')
|
||||
value = list(CONFIGS[server_name])
|
||||
value[4] = idx + 1
|
||||
CONFIGS[extra_domainname] = tuple(value)
|
||||
|
||||
|
||||
async def set_values(server_name, config, datas):
|
||||
try:
|
||||
if 'values' in datas:
|
||||
for path, value in datas['values'].items():
|
||||
if isinstance(value, dict):
|
||||
for idx, val in value.items():
|
||||
await config.option(path, int(idx)).value.set(val)
|
||||
else:
|
||||
await config.option(path).value.set(value)
|
||||
except Exception as err:
|
||||
await value_pprint(await config.value.dict(), config)
|
||||
error_msg = f'cannot configure server "{server_name}": {err}'
|
||||
raise Exception(error_msg) from err
|
||||
#await config.value.dict()
|
||||
|
||||
|
||||
async def valid_mandatories(server_name, config):
|
||||
async def valid_mandatories(config):
|
||||
mandatories = await config.value.mandatory()
|
||||
if mandatories:
|
||||
server_name = None
|
||||
for mandatory in mandatories:
|
||||
path_server_name, path = mandatory.split('.', 1)
|
||||
var_server_name = await config.option(path_server_name).option.description()
|
||||
if server_name != var_server_name:
|
||||
server_name = var_server_name
|
||||
print()
|
||||
print(f'=== Configuration: {server_name} ===')
|
||||
await config.property.pop('mandatory')
|
||||
await value_pprint(await config.value.dict(), config)
|
||||
raise Exception(f'server "{server_name}" has mandatories variables without values "{", ".join(mandatories)}"')
|
||||
print(f'=== Missing variables for {server_name} ===')
|
||||
print(f' - {path}')
|
||||
# await config.property.pop('mandatory')
|
||||
# await value_pprint(await config.value.dict(), config)
|
||||
exit(1)
|
||||
#raise Exception('configuration has mandatories variables without values')
|
||||
|
||||
|
||||
def load_config(copy_manual_dir=False, clean_directories=False):
|
||||
def load_config(copy_manual_dir=False,
|
||||
copy_tests=False,
|
||||
clean_directories=False,
|
||||
):
|
||||
module_infos = {}
|
||||
applications = list_applications()
|
||||
with open('servers.json', 'r') as server_fh:
|
||||
|
@ -225,74 +233,46 @@ def load_config(copy_manual_dir=False, clean_directories=False):
|
|||
modules = jsonfile['modules']
|
||||
for module_name, datas in modules.items():
|
||||
providers = {}
|
||||
suppliers = {}
|
||||
install_dir = join(RISOTTO_CONFIG['directories']['dest'], module_name)
|
||||
if clean_directories:
|
||||
if isdir(install_dir):
|
||||
rmtree(install_dir)
|
||||
makedirs(install_dir)
|
||||
module_infos[module_name] = {'infos': load_image_informations(install_dir,
|
||||
module_infos[module_name] = {'infos': load_image_informations(module_name,
|
||||
install_dir,
|
||||
datas,
|
||||
applications,
|
||||
copy_manual_dir,
|
||||
copy_tests,
|
||||
providers,
|
||||
suppliers,
|
||||
),
|
||||
'providers': providers,
|
||||
'suppliers': suppliers,
|
||||
'install_dir': install_dir,
|
||||
}
|
||||
return module_infos
|
||||
|
||||
|
||||
|
||||
async def load(display_name=None,
|
||||
clean_directories=False,
|
||||
copy_manual_dir=False,
|
||||
hide_secret=False,
|
||||
#
|
||||
#
|
||||
def load_module_config(module_name: str,
|
||||
module_info: dict,
|
||||
):
|
||||
# load images
|
||||
module_infos = load_config(copy_manual_dir, clean_directories)
|
||||
# load machines
|
||||
ZONES_SERVER['providers'] = {}
|
||||
for server_name, datas in SERVERS.items():
|
||||
if server_name in CONFIGS:
|
||||
raise Exception(f'server "{server_name}" is duplicate')
|
||||
module_info = module_infos[datas['module']]
|
||||
CONFIGS[server_name] = await load_machine_config(server_name,
|
||||
datas,
|
||||
module_info,
|
||||
display_name=display_name,
|
||||
)
|
||||
if module_info['providers'] and 'informations' in datas and 'zones_name' in datas['informations']:
|
||||
for zone_idx, zone_name in enumerate(datas['informations']['zones_name']):
|
||||
if not zone_idx:
|
||||
sname = server_name
|
||||
else:
|
||||
sname = datas['informations']['extra_domainnames'][zone_idx - 1]
|
||||
ZONES_SERVER['providers'].setdefault(zone_name, {})
|
||||
for provider in module_info['providers']:
|
||||
ZONES_SERVER['providers'][zone_name].setdefault(provider, []).append(sname)
|
||||
# set servers.json values
|
||||
for server_name, datas in SERVERS.items():
|
||||
config = CONFIGS[server_name]['config']
|
||||
await load_informations(server_name, datas, config)
|
||||
await config.property.read_write()
|
||||
if hide_secret:
|
||||
try:
|
||||
await config.option('general.hide_secret').value.set(True)
|
||||
except AttributeError:
|
||||
pass
|
||||
await set_values(server_name, config, datas)
|
||||
await config.property.read_only()
|
||||
# force calculates all values (for linked values)
|
||||
for server_name in SERVERS:
|
||||
config = CONFIGS[server_name]['config']
|
||||
await config.property.pop('mandatory')
|
||||
try:
|
||||
await config.value.dict()
|
||||
except Exception as err:
|
||||
raise Exception(f'cannot display config for "{server_name}": {err}')
|
||||
await config.property.add('mandatory')
|
||||
# validate mandatories values
|
||||
for server_name in SERVERS:
|
||||
await valid_mandatories(server_name, CONFIGS[server_name]['config'])
|
||||
|
||||
return module_infos
|
||||
cfg = RougailConfig.copy()
|
||||
cfg['variable_namespace'] = ROUGAIL_NAMESPACE
|
||||
cfg['variable_namespace_description'] = ROUGAIL_NAMESPACE_DESCRIPTION
|
||||
if module_name == 'host':
|
||||
#FIXME server_name == host ?
|
||||
#FIXME cfg['tmpfile_dest_dir'] = datas['values'][f'{ROUGAIL_NAMESPACE}.host_install_dir'] + '/host/configurations/host'
|
||||
cfg['default_systemd_directory'] = '/usr/local/lib/systemd'
|
||||
cfg['templates_dir'] = module_info['infos'].templates_dir
|
||||
cfg['dictionaries_dir'] = module_info['infos'].dictionaries_dir
|
||||
cfg['functions_file'] = module_info['infos'].functions_file
|
||||
cfg['multi_functions'] = MULTI_FUNCTIONS
|
||||
cfg['extra_dictionaries'] = module_info['infos'].extra_dictionaries
|
||||
cfg['extra_annotators'] = ['risotto.rougail']
|
||||
cfg['internal_functions'] = list(FUNCTIONS.keys())
|
||||
cfg['force_convert_dyn_option_description'] = True
|
||||
cfg['module_name'] = module_name
|
||||
#cfg['patches_dir'] = join(test_dir, 'patches')
|
||||
return cfg
|
||||
|
|
|
@ -1,342 +1,31 @@
|
|||
from os import makedirs
|
||||
from os.path import join, isdir
|
||||
from warnings import warn_explicit
|
||||
from typing import Any
|
||||
|
||||
from tiramisu import Config
|
||||
from tiramisu.error import ValueWarning
|
||||
from .utils import SERVERS, SERVERS_JSON, MULTI_FUNCTIONS, load_domains
|
||||
from .image import load_config, valid_mandatories # , load_modules_rougail_config
|
||||
from rougail import RougailConfig, RougailConvert
|
||||
from .utils import MULTI_FUNCTIONS, CONFIGS, DOMAINS, value_pprint
|
||||
from .rougail.annotator import calc_providers, calc_providers_global, calc_providers_dynamic, calc_providers_dynamic_follower, calc_providers_follower
|
||||
from os import makedirs
|
||||
#
|
||||
from tiramisu import Config
|
||||
from .utils import value_pprint
|
||||
from rougail.utils import normalize_family
|
||||
from rougail import RougailSystemdTemplate
|
||||
|
||||
|
||||
ROUGAIL_NAMESPACE = 'general'
|
||||
ROUGAIL_NAMESPACE_DESCRIPTION = 'Général'
|
||||
|
||||
|
||||
async def set_linked_multi_variables(value: str,
|
||||
linked_server: str=None,
|
||||
variable_index: int=None,
|
||||
linked_returns: str=None,
|
||||
dynamic: str=None,
|
||||
**kwargs: dict,
|
||||
) -> None:
|
||||
if value is not None and linked_server is not None and 'linked_value_0' not in kwargs:
|
||||
kwargs['linked_value_0'] = value
|
||||
elif not linked_server:
|
||||
linked_server = value
|
||||
if not linked_server:
|
||||
#
|
||||
#
|
||||
async def set_values(server_name, config, datas):
|
||||
if 'values' not in datas:
|
||||
return
|
||||
if linked_server not in CONFIGS:
|
||||
warn_explicit(ValueWarning(f'cannot find linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
3,
|
||||
)
|
||||
return
|
||||
config = CONFIGS[linked_server]['config']
|
||||
dico = {}
|
||||
variables = {}
|
||||
for key, kvalue in kwargs.items():
|
||||
server_path = normalize_family(server_name)
|
||||
for vpath, value in datas['values'].items():
|
||||
path = f'{server_path}.{vpath}'
|
||||
try:
|
||||
index = int(key.rsplit('_', 1)[-1])
|
||||
except ValueError:
|
||||
raise Exception(f'unknown variable {key}')
|
||||
if kvalue is None and not kwargs.get(f'allow_none_{index}', False):
|
||||
return
|
||||
if f'linked_value_{index}' not in kwargs:
|
||||
# value is disabled
|
||||
continue
|
||||
if key.startswith('linked_provider_'):
|
||||
path = await config.information.get('provider:' + kvalue, None)
|
||||
if not path:
|
||||
return
|
||||
if index not in variables:
|
||||
variables[index] = {'path': None, 'value': None, 'variable_index': False}
|
||||
variables[index]['path'] = path
|
||||
elif key.startswith('linked_value_'):
|
||||
index = int(key[13])
|
||||
if index not in variables:
|
||||
variables[index] = {'path': None, 'value': None, 'variable_index': False}
|
||||
variables[index]['value'] = kvalue
|
||||
elif key.startswith('variable_index_'):
|
||||
index = int(key[15])
|
||||
if index not in variables:
|
||||
variables[index] = {'path': None, 'value': None, 'variable_index': False}
|
||||
variables[index]['variable_index'] = True
|
||||
elif key.startswith('allow_none_'):
|
||||
pass
|
||||
if isinstance(value, dict):
|
||||
for idx, val in value.items():
|
||||
await config.option(path, int(idx)).value.set(val)
|
||||
else:
|
||||
raise AttributeError(f'unknown parameter {key}')
|
||||
await config.property.read_write()
|
||||
if not isinstance(variables[0]['value'], list):
|
||||
variables[0]['value'] = [variables[0]['value']]
|
||||
if dynamic:
|
||||
dynamic = normalize_family(dynamic)
|
||||
_dynamic = None
|
||||
try:
|
||||
if variables[0]['value']:
|
||||
for first_idx, first_value in enumerate(variables[0]['value']):
|
||||
slave_idxes = []
|
||||
if dynamic:
|
||||
_dynamic = dynamic
|
||||
else:
|
||||
_dynamic = normalize_family(first_value)
|
||||
for index in sorted(list(variables)):
|
||||
path = variables[index]['path']
|
||||
if '{suffix}' in path:
|
||||
path = path.replace('{suffix}', _dynamic)
|
||||
elif first_idx != 0:
|
||||
continue
|
||||
vvalue = variables[index]['value']
|
||||
option = config.forcepermissive.option(path)
|
||||
if not await option.option.isfollower():
|
||||
#print('===>', path, vvalue, await option.option.ismulti(), await option.option.issubmulti())
|
||||
multi = await option.option.ismulti()
|
||||
if multi:
|
||||
isleader = await option.option.isleader()
|
||||
if not isinstance(vvalue, list):
|
||||
vvalue = [vvalue]
|
||||
# elif isleader:
|
||||
# raise Exception('leader must not be a multi from now ...')
|
||||
values = await option.value.get()
|
||||
for val in vvalue:
|
||||
if val not in values:
|
||||
if isleader:
|
||||
slave_idxes.append(len(values))
|
||||
values.append(val)
|
||||
elif isleader:
|
||||
slave_idxes.append(values.index(val))
|
||||
await option.value.set(values)
|
||||
await option.owner.set('link')
|
||||
else:
|
||||
if isinstance(vvalue, list) and len(vvalue) == 1:
|
||||
vvalue = vvalue[0]
|
||||
await option.value.set(vvalue)
|
||||
await option.owner.set('link')
|
||||
else:
|
||||
# print('===<', path, vvalue, await option.option.ismulti(), await option.option.issubmulti())
|
||||
if not slave_idxes:
|
||||
raise Exception('please declare the leader variable before the follower')
|
||||
if variables[index]['variable_index']:
|
||||
vvalue = vvalue[variable_index]
|
||||
if not isinstance(vvalue, list):
|
||||
vvalue = [vvalue] * len(slave_idxes)
|
||||
# if isinstance(vvalue, list) and not await option.option.issubmulti():
|
||||
for idx, val in enumerate(vvalue):
|
||||
option = config.forcepermissive.option(path, slave_idxes[idx])
|
||||
await option.value.set(val)
|
||||
await option.owner.set('link')
|
||||
await config.option(path).value.set(value)
|
||||
except Exception as err:
|
||||
await config.property.read_only()
|
||||
raise err from err
|
||||
await config.property.read_only()
|
||||
if not dynamic:
|
||||
dynamic = _dynamic
|
||||
|
||||
|
||||
if linked_returns is not None:
|
||||
linked_variable = await config.information.get('provider:' + linked_returns, None)
|
||||
if not linked_variable:
|
||||
warn_explicit(ValueWarning(f'cannot find linked variable "{linked_returns}" in linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
0,
|
||||
)
|
||||
return
|
||||
if dynamic:
|
||||
linked_variable = linked_variable.replace('{suffix}', normalize_family(dynamic))
|
||||
elif '{suffix}' in linked_variable:
|
||||
idx = CONFIGS[linked_server]['interface_index']
|
||||
linked_variable = linked_variable.replace('{suffix}', str(idx))
|
||||
ret = await config.forcepermissive.option(linked_variable).value.get()
|
||||
else:
|
||||
ret = get_ip_from_domain(linked_server)
|
||||
return ret
|
||||
|
||||
|
||||
async def set_linked(linked_server: str,
|
||||
linked_provider: str,
|
||||
linked_value: str,
|
||||
linked_returns: str=None,
|
||||
dynamic: str=None,
|
||||
):
|
||||
if None in (linked_server, linked_provider, linked_value):
|
||||
return
|
||||
if linked_server not in CONFIGS:
|
||||
warn_explicit(ValueWarning(f'cannot find linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
0,
|
||||
)
|
||||
return
|
||||
config = CONFIGS[linked_server]['config']
|
||||
path = await config.information.get('provider:' + linked_provider, None)
|
||||
if not path:
|
||||
warn_explicit(ValueWarning(f'cannot find provider "{linked_provider}" in linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
0,
|
||||
)
|
||||
return
|
||||
await config.property.read_write()
|
||||
try:
|
||||
option = config.forcepermissive.option(path)
|
||||
if await option.option.ismulti():
|
||||
values = await option.value.get()
|
||||
if linked_value not in values:
|
||||
values.append(linked_value)
|
||||
await option.value.set(values)
|
||||
await option.owner.set('link')
|
||||
else:
|
||||
await option.value.set(linked_value)
|
||||
await option.owner.set('link')
|
||||
except Exception as err:
|
||||
await config.property.read_only()
|
||||
raise err from err
|
||||
await config.property.read_only()
|
||||
if linked_returns is not None:
|
||||
linked_variable = await config.information.get('provider:' + linked_returns, None)
|
||||
if not linked_variable:
|
||||
warn_explicit(ValueWarning(f'cannot find linked variable "{linked_returns}" in linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
0,
|
||||
)
|
||||
return
|
||||
else:
|
||||
linked_variable = None
|
||||
if linked_variable is not None:
|
||||
if dynamic:
|
||||
linked_variable = linked_variable.replace('{suffix}', normalize_family(dynamic))
|
||||
elif '{suffix}' in linked_variable:
|
||||
idx = CONFIGS[linked_server]['interface_index']
|
||||
linked_variable = linked_variable.replace('{suffix}', str(idx))
|
||||
ret = await config.forcepermissive.option(linked_variable).value.get()
|
||||
else:
|
||||
ret = normalize_family(linked_value)
|
||||
return ret
|
||||
|
||||
|
||||
async def get_linked_configuration(linked_server: str,
|
||||
linked_provider: str,
|
||||
dynamic: str=None,
|
||||
):
|
||||
if linked_server not in CONFIGS:
|
||||
warn_explicit(ValueWarning(f'cannot find linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
1,
|
||||
)
|
||||
return
|
||||
config = CONFIGS[linked_server]['config']
|
||||
path = await config.information.get('provider:' + linked_provider, None)
|
||||
if not path:
|
||||
warn_explicit(ValueWarning(f'cannot find variable "{path}" in linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
1,
|
||||
)
|
||||
return
|
||||
if dynamic:
|
||||
path = path.replace('{suffix}', normalize_family(dynamic))
|
||||
try:
|
||||
return await config.forcepermissive.option(path).value.get()
|
||||
except AttributeError as err:
|
||||
warn_explicit(ValueWarning(f'cannot find get value of "{path}" in linked server "{linked_server}": {err}'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
1,
|
||||
)
|
||||
|
||||
|
||||
class Empty:
|
||||
pass
|
||||
empty = Empty()
|
||||
|
||||
|
||||
async def set_linked_configuration(_linked_value: Any,
|
||||
linked_server: str,
|
||||
linked_provider: str,
|
||||
linked_value: Any=empty,
|
||||
dynamic: str=None,
|
||||
leader_provider: str=None,
|
||||
leader_value: Any=None,
|
||||
leader_index: int=None,
|
||||
):
|
||||
if linked_value is not empty:
|
||||
_linked_value = linked_value
|
||||
linked_value = _linked_value
|
||||
if linked_server is None:
|
||||
return
|
||||
if linked_value is None or linked_server not in CONFIGS:
|
||||
warn_explicit(ValueWarning(f'cannot find linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
2,
|
||||
)
|
||||
return
|
||||
config = CONFIGS[linked_server]['config']
|
||||
path = await config.information.get('provider:' + linked_provider, None)
|
||||
if not path:
|
||||
warn_explicit(ValueWarning(f'cannot find variable "{path}" in linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
2,
|
||||
)
|
||||
return
|
||||
if dynamic:
|
||||
path = path.replace('{suffix}', normalize_family(dynamic))
|
||||
await config.property.read_write()
|
||||
try:
|
||||
if leader_provider is not None:
|
||||
leader_path = await config.information.get('provider:' + leader_provider, None)
|
||||
if not leader_path:
|
||||
await config.property.read_only()
|
||||
warn_explicit(ValueWarning(f'cannot find leader variable with leader_provider "{leader_provider}" in linked server "{linked_server}"'),
|
||||
ValueWarning,
|
||||
__file__,
|
||||
2,
|
||||
)
|
||||
return
|
||||
if dynamic:
|
||||
leader_path = leader_path.replace('{suffix}', normalize_family(dynamic))
|
||||
values = await config.forcepermissive.option(leader_path).value.get()
|
||||
if not isinstance(leader_value, list):
|
||||
leader_value = [leader_value]
|
||||
for lv in leader_value:
|
||||
if lv in values:
|
||||
slave_idx = values.index(lv)
|
||||
slave_option = config.forcepermissive.option(path, slave_idx)
|
||||
if await slave_option.option.issubmulti():
|
||||
slave_values = await slave_option.value.get()
|
||||
if linked_value not in slave_values:
|
||||
slave_values.append(linked_value)
|
||||
await slave_option.value.set(slave_values)
|
||||
await slave_option.owner.set('link')
|
||||
else:
|
||||
await slave_option.value.set(linked_value)
|
||||
await slave_option.owner.set('link')
|
||||
else:
|
||||
option = config.forcepermissive.option(path, leader_index)
|
||||
if leader_index is None and await option.option.ismulti() and not isinstance(linked_value, list):
|
||||
values = await option.value.get()
|
||||
if linked_value not in values:
|
||||
values.append(linked_value)
|
||||
await option.value.set(values)
|
||||
await option.owner.set('link')
|
||||
else:
|
||||
await option.value.set(linked_value)
|
||||
await option.owner.set('link')
|
||||
except AttributeError as err:
|
||||
if linked_provider == 'oauth2_external':
|
||||
raise ValueError(str(err)) from err
|
||||
pass
|
||||
except Exception as err:
|
||||
await config.property.read_only()
|
||||
raise err from err
|
||||
await config.property.read_only()
|
||||
await value_pprint(await config.value.dict(), config)
|
||||
error_msg = f'cannot configure variable {vpath} for server "{server_name}": {err}'
|
||||
raise Exception(error_msg) from err
|
||||
|
||||
|
||||
def get_ip_from_domain(domain):
|
||||
|
@ -344,58 +33,17 @@ def get_ip_from_domain(domain):
|
|||
return
|
||||
hostname, domainname = domain.split('.', 1)
|
||||
return DOMAINS[domainname][1][DOMAINS[domainname][0].index(hostname)]
|
||||
return optiondescription['option_0']
|
||||
|
||||
|
||||
async def load_machine_config(server_name: str,
|
||||
datas: dict,
|
||||
module_info: dict,
|
||||
display_name,
|
||||
):
|
||||
optiondescription = {'set_linked': set_linked,
|
||||
'set_linked_multi_variables': set_linked_multi_variables,
|
||||
'get_linked_configuration': get_linked_configuration,
|
||||
'set_linked_configuration': set_linked_configuration,
|
||||
'get_ip_from_domain': get_ip_from_domain,
|
||||
}
|
||||
cfg = RougailConfig.copy()
|
||||
module_info['infos'].servers.append(server_name)
|
||||
cfg['variable_namespace'] = ROUGAIL_NAMESPACE
|
||||
cfg['variable_namespace_description'] = ROUGAIL_NAMESPACE_DESCRIPTION
|
||||
if datas['module'] == 'host':
|
||||
cfg['tmpfile_dest_dir'] = datas['values'][f'{ROUGAIL_NAMESPACE}.host_install_dir'] + '/host/configurations/' + server_name
|
||||
cfg['templates_dir'] = module_info['infos'].templates_dir
|
||||
cfg['dictionaries_dir'] = module_info['infos'].dictionaries_dir
|
||||
cfg['functions_file'] = module_info['infos'].functions_file
|
||||
cfg['multi_functions'] = MULTI_FUNCTIONS
|
||||
cfg['extra_dictionaries'] = module_info['infos'].extra_dictionaries
|
||||
cfg['extra_annotators'].append('risotto.rougail')
|
||||
cfg['internal_functions'] = list(optiondescription.keys())
|
||||
try:
|
||||
eolobj = RougailConvert(cfg)
|
||||
except Exception as err:
|
||||
print(f"Try to load {module_info['infos'].modules}")
|
||||
raise err from err
|
||||
tiram_obj = eolobj.save(None)
|
||||
# if server_name == 'revprox.in.silique.fr':
|
||||
# print(tiram_obj)
|
||||
#cfg['patches_dir'] = join(test_dir, 'patches')
|
||||
try:
|
||||
exec(tiram_obj, None, optiondescription)
|
||||
except Exception as err:
|
||||
print(tiram_obj)
|
||||
raise Exception(f'unknown error when load tiramisu object {err}') from err
|
||||
config = await Config(optiondescription['option_0'], display_name=display_name)
|
||||
await config.property.read_write()
|
||||
try:
|
||||
add_srv = await config.option('machine.add_srv').value.get()
|
||||
except AttributeError:
|
||||
add_srv = False
|
||||
return {'config': config,
|
||||
'templates_informations': cfg,
|
||||
'interface_index': 0,
|
||||
'module_name': datas['module'],
|
||||
'add_srv': add_srv,
|
||||
'providers': module_info['providers'],
|
||||
ROUGAIL_NAMESPACE = 'general'
|
||||
ROUGAIL_NAMESPACE_DESCRIPTION = 'Général'
|
||||
FUNCTIONS = {'get_ip_from_domain': get_ip_from_domain,
|
||||
'calc_providers': calc_providers,
|
||||
'calc_providers_global': calc_providers_global,
|
||||
'calc_providers_dynamic': calc_providers_dynamic,
|
||||
'calc_providers_dynamic_follower': calc_providers_dynamic_follower,
|
||||
'calc_providers_follower': calc_providers_follower,
|
||||
}
|
||||
|
||||
|
||||
|
@ -404,24 +52,100 @@ async def templates(server_name,
|
|||
templates_informations,
|
||||
srv=False,
|
||||
just_copy=False,
|
||||
**kwargs,
|
||||
):
|
||||
values = await config.value.dict()
|
||||
engine = RougailSystemdTemplate(config, templates_informations)
|
||||
if just_copy:
|
||||
# for all engine to none
|
||||
ori_engines = {}
|
||||
for eng in engine.engines:
|
||||
if eng != 'none':
|
||||
if eng == 'none':
|
||||
continue
|
||||
ori_engines[eng] = engine.engines[eng]
|
||||
engine.engines[eng] = engine.engines['none']
|
||||
# if server_name == 'dovecot.in.silique.fr':
|
||||
# print()
|
||||
# print(f'=== Configuration: {server_name} ===')
|
||||
# pprint(values)
|
||||
try:
|
||||
await engine.instance_files()
|
||||
except Exception as err:
|
||||
print()
|
||||
print(f'=== Configuration: {server_name} ===')
|
||||
values = await config.value.dict()
|
||||
await value_pprint(values, config)
|
||||
raise err from err
|
||||
print(err)
|
||||
print(await config.option('general.nginx.nginx_default_http').value.get())
|
||||
exit(1)
|
||||
#raise err from err
|
||||
if just_copy:
|
||||
for eng, old_engine in ori_engines.items():
|
||||
engine.engines[eng] = old_engine
|
||||
if srv:
|
||||
makedirs(srv)
|
||||
|
||||
|
||||
|
||||
async def load(display_name=None,
|
||||
clean_directories=False,
|
||||
copy_manual_dir=False,
|
||||
copy_tests=False,
|
||||
hide_secret=False,
|
||||
):
|
||||
#load_zones()
|
||||
# # load images
|
||||
#FIXME useful
|
||||
module_infos = load_config(copy_manual_dir,
|
||||
copy_tests,
|
||||
clean_directories,
|
||||
)
|
||||
# modules_rougail_config = load_modules_rougail_config(module_infos)
|
||||
cfg = RougailConfig.copy()
|
||||
cfg['variable_namespace'] = ROUGAIL_NAMESPACE
|
||||
cfg['variable_namespace_description'] = ROUGAIL_NAMESPACE_DESCRIPTION
|
||||
cfg['multi_functions'] = MULTI_FUNCTIONS
|
||||
cfg['extra_annotators'] = ['risotto.rougail']
|
||||
cfg['internal_functions'] = list(FUNCTIONS.keys())
|
||||
cfg['force_convert_dyn_option_description'] = True
|
||||
# cfg['module_name'] = module_name
|
||||
functions_files = set()
|
||||
load_domains()
|
||||
for server_name, datas in SERVERS.items():
|
||||
module_info = module_infos[datas['module']]
|
||||
functions_files |= set(module_info['infos'].functions_file)
|
||||
cfg['functions_file'] = list(functions_files)
|
||||
eolobj = RougailConvert(cfg)
|
||||
cfg['risotto_globals'] = {}
|
||||
for server_name, datas in SERVERS.items():
|
||||
module_info = module_infos[datas['module']]
|
||||
cfg['dictionaries_dir'] = module_info['infos'].dictionaries_dir
|
||||
cfg['extra_dictionaries'] = module_info['infos'].extra_dictionaries
|
||||
informations = SERVERS_JSON['servers'][server_name].get('informations')
|
||||
if informations:
|
||||
cfg['risotto_globals'][server_name] = {'global:server_name': server_name,
|
||||
'global:zones_name': informations['zones_name'],
|
||||
'global:zones_list': list(range(len(informations['zones_name']))),
|
||||
}
|
||||
values = []
|
||||
for s_idx in cfg['risotto_globals'][server_name]['global:zones_list']:
|
||||
if not s_idx:
|
||||
values.append(server_name)
|
||||
else:
|
||||
values.append(informations['extra_domainnames'][s_idx - 1])
|
||||
cfg['risotto_globals'][server_name]['global:server_names'] = values
|
||||
else:
|
||||
cfg['risotto_globals'][server_name] = {'global:server_name': server_name}
|
||||
eolobj.load_dictionaries(path_prefix=server_name)
|
||||
tiram_obj = eolobj.save(None)
|
||||
optiondescription = FUNCTIONS.copy()
|
||||
try:
|
||||
exec(tiram_obj, None, optiondescription)
|
||||
except Exception as err:
|
||||
print(tiram_obj)
|
||||
raise Exception(f'unknown error when load tiramisu object {err}') from err
|
||||
config = await Config(optiondescription['option_0'],
|
||||
display_name=display_name,
|
||||
)
|
||||
await config.property.pop('validator')
|
||||
await config.property.pop('cache')
|
||||
for server_name, datas in SERVERS.items():
|
||||
await set_values(server_name, config, datas)
|
||||
await config.property.read_only()
|
||||
await config.property.add('cache')
|
||||
await valid_mandatories(config)
|
||||
return module_infos, cfg, config
|
||||
|
|
|
@ -1,5 +1,122 @@
|
|||
from rougail.annotator.variable import Walk
|
||||
from risotto.utils import _
|
||||
from risotto.utils import _, multi_function
|
||||
from warnings import warn
|
||||
|
||||
|
||||
|
||||
def _parse_kwargs(provider, dns, kwargs, index=None):
|
||||
values = {}
|
||||
for key, value in kwargs.items():
|
||||
if '_' not in key:
|
||||
raise Exception(f'unknown attribute {key} in calc_providers_global with provider {provider}')
|
||||
k, idx = key.rsplit('_', 1)
|
||||
values.setdefault(idx, {})[k] = value
|
||||
for idx, data in values.items():
|
||||
if index is not None and int(idx) != index:
|
||||
continue
|
||||
if 'dns' not in data or (isinstance(data['dns'], list) and dns not in data['dns']) or (not isinstance(data['dns'], list) and data['dns'] != dns):
|
||||
continue
|
||||
del data['dns']
|
||||
yield data
|
||||
|
||||
|
||||
@multi_function
|
||||
def calc_providers_global(provider, multi, value, suffix=None):
|
||||
if suffix is not None:
|
||||
return value[int(suffix)]
|
||||
return value
|
||||
|
||||
|
||||
@multi_function
|
||||
def calc_providers_follower(provider, multi, dns, leader, index, **kwargs):
|
||||
ret = []
|
||||
for data in _parse_kwargs(provider, dns, kwargs):
|
||||
if 'value' not in data:
|
||||
continue
|
||||
if 'leader' in data:
|
||||
if isinstance(data['leader'], list):
|
||||
for idx, leader_iter in enumerate(data['leader']):
|
||||
if leader_iter == leader:
|
||||
ret.append(data['value'][idx])
|
||||
elif data['leader']== leader:
|
||||
ret.extend(data['value'])
|
||||
else:
|
||||
if isinstance(data['value'], list):
|
||||
for v in data['value']:
|
||||
if v not in ret:
|
||||
ret.append(v)
|
||||
elif data['value'] not in ret:
|
||||
ret.append(data['value'])
|
||||
if multi:
|
||||
return ret
|
||||
if ret:
|
||||
return ret[0]
|
||||
|
||||
|
||||
@multi_function
|
||||
def calc_providers_dynamic_follower(provider, multi, dns, leader, index, suffix, **kwargs):
|
||||
ret = []
|
||||
for data in _parse_kwargs(provider, dns, kwargs):
|
||||
if 'value' not in data:
|
||||
continue
|
||||
if data['dynamic'] != suffix:
|
||||
continue
|
||||
if 'leader' in data:
|
||||
for idx, leader_iter in enumerate(data['leader']):
|
||||
if leader_iter == leader:
|
||||
if isinstance(data['value'], list):
|
||||
ret.append(data['value'][idx])
|
||||
else:
|
||||
ret.append(data['value'])
|
||||
else:
|
||||
if isinstance(data['value'], list):
|
||||
for v in data['value']:
|
||||
if v not in ret:
|
||||
ret.append(v)
|
||||
elif data['value'] not in ret:
|
||||
ret.append(data['value'])
|
||||
if multi:
|
||||
return ret
|
||||
if ret:
|
||||
return ret[0]
|
||||
|
||||
|
||||
@multi_function
|
||||
def calc_providers_dynamic(provider, multi, dns, suffix, **kwargs):
|
||||
ret = []
|
||||
for data in _parse_kwargs(provider, dns, kwargs):
|
||||
if 'value' not in data:
|
||||
continue
|
||||
if data['dynamic'] != suffix:
|
||||
continue
|
||||
if isinstance(data['value'], list):
|
||||
for v in data['value']:
|
||||
if v not in ret:
|
||||
ret.append(v)
|
||||
elif data['value'] not in ret:
|
||||
ret.append(data['value'])
|
||||
if multi:
|
||||
return ret
|
||||
if ret:
|
||||
return ret[0]
|
||||
|
||||
|
||||
@multi_function
|
||||
def calc_providers(provider, multi, dns, suffix=None, **kwargs):
|
||||
ret = []
|
||||
for data in _parse_kwargs(provider, dns, kwargs):
|
||||
if isinstance(data['value'], list):
|
||||
for v in data['value']:
|
||||
if v in ret:
|
||||
continue
|
||||
ret.append(v)
|
||||
|
||||
elif data['value'] not in ret:
|
||||
ret.append(data['value'])
|
||||
if multi:
|
||||
return ret
|
||||
if ret:
|
||||
return ret[0]
|
||||
|
||||
|
||||
class Annotator(Walk):
|
||||
|
@ -10,48 +127,217 @@ class Annotator(Walk):
|
|||
self.objectspace = objectspace
|
||||
# self.convert_get_linked_information()
|
||||
# self.convert_provider()
|
||||
self.set_suppliers()
|
||||
self.convert_providers()
|
||||
self.convert_suppliers()
|
||||
|
||||
def convert_get_linked_information(self):
|
||||
if not hasattr(self.objectspace.space, 'constraints') or \
|
||||
not hasattr(self.objectspace.space.constraints, 'fill'):
|
||||
return
|
||||
for fill in self.objectspace.space.constraints.fill:
|
||||
if fill.name == 'get_linked_configuration':
|
||||
# add server_name
|
||||
param = self.objectspace.param(fill.xmlfiles)
|
||||
param.name = 'server_name'
|
||||
param.type = 'information'
|
||||
param.text = 'server_name'
|
||||
fill.param.append(param)
|
||||
# add current_user
|
||||
param = self.objectspace.param(fill.xmlfiles)
|
||||
param.name = 'current_user'
|
||||
param.type = 'information'
|
||||
param.text = 'current_user'
|
||||
fill.param.append(param)
|
||||
# add test
|
||||
param = self.objectspace.param(fill.xmlfiles)
|
||||
param.name = 'test'
|
||||
param.type = 'target_information'
|
||||
param.text = 'test'
|
||||
fill.param.append(param)
|
||||
|
||||
def convert_provider(self):
|
||||
if not hasattr(self.objectspace.space, 'variables'):
|
||||
return
|
||||
for family in self.get_families():
|
||||
if not hasattr(family, 'provider'):
|
||||
def set_suppliers(self) -> dict:
|
||||
""" get supplier informations
|
||||
return something like:
|
||||
{'Host': ['host1.example.net', 'host2.example.net']}
|
||||
"""
|
||||
self.suppliers = {}
|
||||
for variable in self.get_variables():
|
||||
if not hasattr(variable, 'supplier') or ':' in variable.supplier:
|
||||
continue
|
||||
if 'dynamic' not in vars(family):
|
||||
raise Exception(_(f'{family.name} is not a dynamic family so cannot have provider attribute'))
|
||||
if not hasattr(family, 'information'):
|
||||
family.information = self.objectspace.information(family.xmlfiles)
|
||||
family.information.provider = family.provider
|
||||
del family.provider
|
||||
nf_dns = variable.path.split('.', 1)[0]
|
||||
server_name = self.objectspace.space.variables[nf_dns].doc
|
||||
self.suppliers.setdefault(variable.supplier, []).append({'option': variable, 'dns': server_name, 'path_prefix': nf_dns, 'zones': set(self.objectspace.rougailconfig['risotto_globals'][server_name]['global:zones_name'])})
|
||||
|
||||
def convert_suppliers(self):
|
||||
for supplier, data in self.suppliers.items():
|
||||
if supplier == 'Host':
|
||||
continue
|
||||
for s_dico in data:
|
||||
if supplier not in self.providers:
|
||||
continue
|
||||
for p_dico in self.providers[supplier]:
|
||||
if s_dico['zones'] & p_dico['zones']:
|
||||
s_dico['option'].value = p_dico['dns']
|
||||
new_value = self.objectspace.value(None)
|
||||
new_value.name = p_dico['dns']
|
||||
s_dico['option'].value = [new_value]
|
||||
break
|
||||
|
||||
|
||||
def convert_providers(self):
|
||||
self.providers = {}
|
||||
for variable in self.get_variables():
|
||||
if not hasattr(variable, 'provider'):
|
||||
continue
|
||||
if not hasattr(variable, 'information'):
|
||||
variable.information = self.objectspace.information(variable.xmlfiles)
|
||||
variable.information.provider = variable.provider
|
||||
del variable.provider
|
||||
nf_dns = variable.path.split('.', 1)[0]
|
||||
server_name = self.objectspace.space.variables[nf_dns].doc
|
||||
provider_name = variable.provider
|
||||
if ':' in provider_name:
|
||||
key_name, key_type = provider_name.rsplit(':', 1)
|
||||
is_provider = False
|
||||
else:
|
||||
key_name = key_type = provider_name
|
||||
is_provider = True
|
||||
if provider_name != 'Host':
|
||||
self.providers.setdefault(provider_name, []).append({'option': variable, 'dns': server_name, 'path_prefix': nf_dns, 'zones': set(self.objectspace.rougailconfig['risotto_globals'][server_name]['global:zones_name'])})
|
||||
if key_name != 'global' and key_name not in self.suppliers:
|
||||
#warn(f'cannot find supplier "{key_name}" for "{server_name}"')
|
||||
continue
|
||||
# create a fill for this variable
|
||||
fill = self.objectspace.fill(variable.xmlfiles)
|
||||
new_target = self.objectspace.target(variable.xmlfiles)
|
||||
new_target.name = variable
|
||||
fill.target = [new_target]
|
||||
if key_name == 'global':
|
||||
fill.name = 'calc_providers_global'
|
||||
elif self.objectspace.paths.is_dynamic(variable):
|
||||
if self.objectspace.paths.is_follower(variable):
|
||||
fill.name = 'calc_providers_dynamic_follower'
|
||||
else:
|
||||
fill.name = 'calc_providers_dynamic'
|
||||
elif self.objectspace.paths.is_follower(variable):
|
||||
fill.name = 'calc_providers_follower'
|
||||
else:
|
||||
fill.name = 'calc_providers'
|
||||
fill.namespace = variable.namespace
|
||||
fill.index = 0
|
||||
# first parameter: the provider name (something link Host:incoming_ports)
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = 'provider'
|
||||
param.text = provider_name
|
||||
fill.param = [param]
|
||||
# second parameter: current variable is a multi variable?
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = 'multi'
|
||||
param.text = variable.multi
|
||||
param.type = 'boolean'
|
||||
fill.param.append(param)
|
||||
if self.objectspace.paths.is_follower(variable):
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = 'leader'
|
||||
param.text = self.objectspace.paths.get_leader(variable)
|
||||
param.propertyerror = False
|
||||
param.type = 'variable'
|
||||
fill.param.append(param)
|
||||
try:
|
||||
leader_provider = self.objectspace.paths.get_leader(variable).provider
|
||||
except:
|
||||
leader_provider = None
|
||||
#
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = 'index'
|
||||
param.type = 'index'
|
||||
fill.param.append(param)
|
||||
if self.objectspace.paths.is_dynamic(variable):
|
||||
# if dynamic: current suffix
|
||||
# and add current DNS name, this is useful to known if supplier is link to this provider
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = 'suffix'
|
||||
param.type = 'suffix'
|
||||
fill.param.append(param)
|
||||
if key_name != 'global':
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = 'dns'
|
||||
param.text = server_name
|
||||
fill.param.append(param)
|
||||
if key_name == 'global':
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.text = self.objectspace.rougailconfig['risotto_globals'][server_name][provider_name]
|
||||
param.name = 'value'
|
||||
fill.param.append(param)
|
||||
else:
|
||||
# parse all supplier link to current provider
|
||||
for idx, data in enumerate(self.suppliers[key_name]):
|
||||
option = data['option']
|
||||
dns = data['dns']
|
||||
# if not provider, get the true option that we want has value
|
||||
if not is_provider:
|
||||
path_prefix = data['path_prefix']
|
||||
try:
|
||||
supplier_option = self.objectspace.paths.get_supplier(f'supplier:{provider_name}', path_prefix)
|
||||
except KeyError:
|
||||
#warn(f'cannot find supplier "{provider_name}" for "{dns}"')
|
||||
continue
|
||||
# first of all, get the supplier name
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = f'dns_{idx}'
|
||||
param.text = option
|
||||
param.propertyerror = False
|
||||
param.type = 'variable'
|
||||
fill.param.append(param)
|
||||
if not is_provider and \
|
||||
self.objectspace.paths.is_follower(variable):
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = f'leader_{idx}'
|
||||
if fill.name == 'calc_providers_follower':
|
||||
param.text = dns
|
||||
else:
|
||||
if self.objectspace.paths.is_follower(supplier_option):
|
||||
param.text = self.objectspace.paths.get_leader(supplier_option)
|
||||
else:
|
||||
param.text = self.objectspace.paths.get_supplier(f'supplier:{leader_provider}', path_prefix)
|
||||
param.propertyerror = False
|
||||
param.type = 'variable'
|
||||
fill.param.append(param)
|
||||
# get the current DNS name for dynamic variable
|
||||
if self.objectspace.paths.is_dynamic(variable):
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = f'dynamic_{idx}'
|
||||
param.text = dns
|
||||
fill.param.append(param)
|
||||
# get the current value!
|
||||
param = self.objectspace.param(variable.xmlfiles)
|
||||
param.name = f'value_{idx}'
|
||||
if is_provider:
|
||||
param.text = dns
|
||||
else:
|
||||
param.text = supplier_option
|
||||
param.propertyerror = False
|
||||
param.type = 'variable'
|
||||
fill.param.append(param)
|
||||
if not hasattr(self.objectspace.space.variables[nf_dns], 'constraints'):
|
||||
self.objectspace.space.variables[nf_dns].constraints = self.objectspace.constraints(None)
|
||||
if not hasattr(self.objectspace.space.variables[nf_dns].constraints, 'fill'):
|
||||
self.objectspace.space.variables[nf_dns].constraints.fill = []
|
||||
self.objectspace.space.variables[nf_dns].constraints.fill.append(fill)
|
||||
|
||||
# def convert_get_linked_information(self):
|
||||
# if not hasattr(self.objectspace.space, 'constraints') or \
|
||||
# not hasattr(self.objectspace.space.constraints, 'fill'):
|
||||
# return
|
||||
# for fill in self.objectspace.space.constraints.fill:
|
||||
# if fill.name == 'get_linked_configuration':
|
||||
# # add server_name
|
||||
# param = self.objectspace.param(fill.xmlfiles)
|
||||
# param.name = 'server_name'
|
||||
# param.type = 'information'
|
||||
# param.text = 'server_name'
|
||||
# fill.param.append(param)
|
||||
# # add current_user
|
||||
# param = self.objectspace.param(fill.xmlfiles)
|
||||
# param.name = 'current_user'
|
||||
# param.type = 'information'
|
||||
# param.text = 'current_user'
|
||||
# fill.param.append(param)
|
||||
# # add test
|
||||
# param = self.objectspace.param(fill.xmlfiles)
|
||||
# param.name = 'test'
|
||||
# param.type = 'target_information'
|
||||
# param.text = 'test'
|
||||
# fill.param.append(param)
|
||||
#
|
||||
# def convert_provider(self):
|
||||
# if not hasattr(self.objectspace.space, 'variables'):
|
||||
# return
|
||||
# for family in self.get_families():
|
||||
# if not hasattr(family, 'provider'):
|
||||
# continue
|
||||
# if 'dynamic' not in vars(family):
|
||||
# raise Exception(_(f'{family.name} is not a dynamic family so cannot have provider attribute'))
|
||||
# if not hasattr(family, 'information'):
|
||||
# family.information = self.objectspace.information(family.xmlfiles)
|
||||
# family.information.provider = family.provider
|
||||
# del family.provider
|
||||
# for variable in self.get_variables():
|
||||
# if not hasattr(variable, 'provider'):
|
||||
# continue
|
||||
# if not hasattr(variable, 'information'):
|
||||
# variable.information = self.objectspace.information(variable.xmlfiles)
|
||||
# variable.information.provider = variable.provider
|
||||
# del variable.provider
|
||||
|
|
|
@ -6,12 +6,13 @@ from toml import load as toml_load
|
|||
from pprint import pprint
|
||||
|
||||
|
||||
SETTINGS = {'config': None}
|
||||
MULTI_FUNCTIONS = []
|
||||
CONFIGS = {}
|
||||
DOMAINS = {}
|
||||
ZONES = {}
|
||||
ZONES_SERVER = {}
|
||||
SERVERS_JSON = {}
|
||||
SERVERS = {}
|
||||
CONFIGS = {}
|
||||
|
||||
|
||||
with open(environ.get('CONFIG_FILE', 'risotto.conf'), 'r') as fh:
|
||||
|
@ -40,10 +41,10 @@ async def value_pprint(dico, config):
|
|||
|
||||
|
||||
def load_zones_server():
|
||||
if 'zones' in ZONES_SERVER:
|
||||
if 'zones' in SERVERS_JSON:
|
||||
return
|
||||
with open('servers.json', 'r') as server_fh:
|
||||
ZONES_SERVER.update(load(server_fh))
|
||||
SERVERS_JSON.update(load(server_fh))
|
||||
|
||||
|
||||
def load_zones():
|
||||
|
@ -52,8 +53,8 @@ def load_zones():
|
|||
return
|
||||
|
||||
load_zones_server()
|
||||
ZONES.update(ZONES_SERVER['zones'])
|
||||
for server_name, server in ZONES_SERVER['servers'].items():
|
||||
ZONES.update(SERVERS_JSON['zones'])
|
||||
for server_name, server in SERVERS_JSON['servers'].items():
|
||||
if 'informations' not in server:
|
||||
continue
|
||||
server_zones = server['informations']['zones_name']
|
||||
|
@ -78,7 +79,7 @@ def load_domains():
|
|||
if DOMAINS:
|
||||
return
|
||||
load_zones()
|
||||
for zone_name, zone in ZONES_SERVER['zones'].items():
|
||||
for zone_name, zone in SERVERS_JSON['zones'].items():
|
||||
if 'domain_name' in zone:
|
||||
hosts = []
|
||||
ips = []
|
||||
|
@ -103,5 +104,4 @@ def _get_ip(server_name: str,
|
|||
if server_name not in zone['hosts']:
|
||||
raise ValueError(f"cannot set IP in unknown server '{server_name}'")
|
||||
server_index = zone['hosts'].index(server_name)
|
||||
# print(server_name, zones_name, index, str(ip_address(zone['start_ip']) + server_index))
|
||||
return str(ip_address(zone['start_ip']) + server_index)
|
||||
|
|
|
@ -155,7 +155,7 @@ def gen_cert_iter(cn,
|
|||
raise Exception(f'cannot find CA file "{cert_ca_name}"')
|
||||
if not isfile(cert_name):
|
||||
if not isfile(key_ca_name):
|
||||
raise Exception(f"cannot find CA private key (\"{authority_cn}\") to sign certificat for \"{cn}\", is it a Let's Encrypt certification?")
|
||||
raise Exception(f"cannot find CA private key (\"{authority_cn}\") to sign certificat for \"{cn}\" ({key_ca_name}), is it a Let's Encrypt certification?")
|
||||
if not isdir(dir_name):
|
||||
makedirs(dir_name)
|
||||
if isfile(sn_name):
|
||||
|
|
Loading…
Reference in a new issue