forked from stove/risotto
Compare commits
8 commits
54ff8f23ed
...
6d8219b22c
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d8219b22c | |||
| 96132ae60a | |||
| db86a3d02c | |||
| daf4833691 | |||
| cebb8f970b | |||
| d0aaf99890 | |||
| 833f6e8d4d | |||
| 75bb6b0765 |
9 changed files with 508 additions and 464 deletions
|
|
@ -10,12 +10,40 @@
|
||||||
ansible.builtin.hostname:
|
ansible.builtin.hostname:
|
||||||
name: "{{ inventory_hostname }}"
|
name: "{{ inventory_hostname }}"
|
||||||
|
|
||||||
- name: "Packages installation"
|
- name: "Install packages"
|
||||||
apt:
|
apt:
|
||||||
pkg: "{{ vars[inventory_hostname]['general']['host_packages'] }}"
|
pkg: "{{ vars[inventory_hostname]['general']['host_packages'] }}"
|
||||||
update_cache: yes
|
update_cache: yes
|
||||||
state: latest
|
state: latest
|
||||||
|
|
||||||
|
- name: "Remove packages"
|
||||||
|
apt:
|
||||||
|
pkg: "{{ vars[inventory_hostname]['general']['host_removed_packages'] }}"
|
||||||
|
update_cache: yes
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: "Add keyrings directory"
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: "755"
|
||||||
|
|
||||||
|
- name: "Add vector signed repositories"
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: https://repositories.timber.io/public/vector/gpg.3543DB2D0A2BC4B8.key
|
||||||
|
dest: /etc/apt/keyrings/vector.asc
|
||||||
|
|
||||||
|
- name: "Add vector repository"
|
||||||
|
ansible.builtin.apt_repository:
|
||||||
|
repo: "deb [signed-by=/etc/apt/keyrings/vector.asc] https://repositories.timber.io/public/vector/deb/debian {{ ansible_distribution_release }} main"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: "Install vector"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: vector
|
||||||
|
update_cache: yes
|
||||||
|
state: present
|
||||||
|
|
||||||
- name: "Host is modified"
|
- name: "Host is modified"
|
||||||
include_tasks: host_modified.yml
|
include_tasks: host_modified.yml
|
||||||
when: build_host.host_changed
|
when: build_host.host_changed
|
||||||
|
|
@ -71,25 +99,3 @@
|
||||||
path: /var/lib/risotto/tls
|
path: /var/lib/risotto/tls
|
||||||
state: directory
|
state: directory
|
||||||
mode: "755"
|
mode: "755"
|
||||||
|
|
||||||
- name: "Add keyrings directory"
|
|
||||||
file:
|
|
||||||
path: /etc/apt/keyrings
|
|
||||||
state: directory
|
|
||||||
mode: "755"
|
|
||||||
|
|
||||||
- name: "Add vector signed repositories"
|
|
||||||
ansible.builtin.get_url:
|
|
||||||
url: https://repositories.timber.io/public/vector/gpg.3543DB2D0A2BC4B8.key
|
|
||||||
dest: /etc/apt/keyrings/vector.asc
|
|
||||||
|
|
||||||
- name: "Add vector repository"
|
|
||||||
ansible.builtin.apt_repository:
|
|
||||||
repo: "deb [signed-by=/etc/apt/keyrings/vector.asc] https://repositories.timber.io/public/vector/deb/debian {{ ansible_distribution_release }} main"
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: "Install vector"
|
|
||||||
ansible.builtin.apt:
|
|
||||||
name: vector
|
|
||||||
update_cache: yes
|
|
||||||
state: present
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@
|
||||||
|
|
||||||
- name: "Start services"
|
- name: "Start services"
|
||||||
when: item.value['manage'] and item.value['activate'] and item.value['doc'].endswith('.service') and not item.value['doc'].endswith('@.service') and item.value['engine']
|
when: item.value['manage'] and item.value['activate'] and item.value['doc'].endswith('.service') and not item.value['doc'].endswith('@.service') and item.value['engine']
|
||||||
|
ignore_errors: true
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
name: "{{ item.value['doc'] }}"
|
name: "{{ item.value['doc'] }}"
|
||||||
state: started
|
state: started
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ class RisottoInventory(object):
|
||||||
parser.add_argument('--nocache', action='store_true')
|
parser.add_argument('--nocache', action='store_true')
|
||||||
parser.add_argument('--debug', action='store_true')
|
parser.add_argument('--debug', action='store_true')
|
||||||
parser.add_argument('--pretty_print', action='store_true')
|
parser.add_argument('--pretty_print', action='store_true')
|
||||||
|
parser.add_argument('--quite', action='store_true')
|
||||||
self.args = parser.parse_args()
|
self.args = parser.parse_args()
|
||||||
if self.args.debug:
|
if self.args.debug:
|
||||||
global DEBUG
|
global DEBUG
|
||||||
|
|
@ -75,7 +76,7 @@ class RisottoInventory(object):
|
||||||
'hosts': servers,
|
'hosts': servers,
|
||||||
'vars': {
|
'vars': {
|
||||||
# FIXME
|
# FIXME
|
||||||
# 'ansible_ssh_host': '192.168.0.29',
|
# 'ansible_ssh_host': '192.168.0.28',
|
||||||
'ansible_ssh_user': 'root',
|
'ansible_ssh_user': 'root',
|
||||||
'ansible_python_interpreter': '/usr/bin/python3'
|
'ansible_python_interpreter': '/usr/bin/python3'
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +120,7 @@ def main():
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from json import loads
|
from json import loads
|
||||||
pprint(loads(values))
|
pprint(loads(values))
|
||||||
else:
|
elif not inv.args.quite:
|
||||||
print(values)
|
print(values)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,13 @@ def read_dnf_pkg_file(os_name, filename1, filename2):
|
||||||
sp_line = pkg_line.strip().split()
|
sp_line = pkg_line.strip().split()
|
||||||
if len(sp_line) < idx_version[fidx] + 1:
|
if len(sp_line) < idx_version[fidx] + 1:
|
||||||
continue
|
continue
|
||||||
if sp_line[idx_pkg[fidx]] in pkgs:
|
pkg = sp_line[idx_pkg[fidx]]
|
||||||
raise Exception(f'package already set {sp_line[0]}?')
|
|
||||||
version = sp_line[idx_version[fidx]]
|
version = sp_line[idx_version[fidx]]
|
||||||
|
#if pkg in pkgs:
|
||||||
|
# raise Exception(f'package already set {pkg}?')
|
||||||
if os_name == 'debian' and version.startswith('('):
|
if os_name == 'debian' and version.startswith('('):
|
||||||
version = version[1:]
|
version = version[1:]
|
||||||
pkgs[sp_line[idx_pkg[fidx]]] = version
|
pkgs[pkg] = version
|
||||||
return pkgs
|
return pkgs
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ ls /var/lib/risotto/images_files/ | while read image; do
|
||||||
if [ -d /var/lib/risotto/images_files/"$image" ]; then
|
if [ -d /var/lib/risotto/images_files/"$image" ]; then
|
||||||
echo
|
echo
|
||||||
echo "Install image $image" | tee -a /var/log/risotto/update_images.log
|
echo "Install image $image" | tee -a /var/log/risotto/update_images.log
|
||||||
/usr/local/sbin/build_image "$image" | tee -a /var/log/risotto/update_images.log || (echo "PROBLEME" | tee -a /var/log/risotto/update_images.log; true)
|
/usr/local/sbin/build_image "$image" || echo "PROBLEME" | tee -a /var/log/risotto/update_images.log
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ for nspawn in $(ls /etc/systemd/nspawn/*.nspawn); do
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
if [ ! -d "$MACHINE_MACHINES_DIR" ]; then
|
if [ ! -d "$MACHINE_MACHINES_DIR/etc" ]; then
|
||||||
rm -f "$VERSION_MACHINE"
|
rm -f "$VERSION_MACHINE"
|
||||||
fi
|
fi
|
||||||
diff -q "$RISOTTO_IMAGE_DIR/$IMAGE_NAME_RISOTTO_IMAGE_NAME".version "$VERSION_MACHINE" &> /dev/null || (
|
diff -q "$RISOTTO_IMAGE_DIR/$IMAGE_NAME_RISOTTO_IMAGE_NAME".version "$VERSION_MACHINE" &> /dev/null || (
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ from os import listdir, makedirs
|
||||||
from os.path import join, isdir, isfile, dirname
|
from os.path import join, isdir, isfile, dirname
|
||||||
from yaml import load as yaml_load, SafeLoader
|
from yaml import load as yaml_load, SafeLoader
|
||||||
from tiramisu.error import PropertiesOptionError
|
from tiramisu.error import PropertiesOptionError
|
||||||
|
from .rougail import func
|
||||||
#
|
#
|
||||||
from .utils import RISOTTO_CONFIG
|
from .utils import RISOTTO_CONFIG
|
||||||
|
|
||||||
|
|
@ -11,7 +12,7 @@ class ModuleCfg():
|
||||||
def __init__(self, module_name):
|
def __init__(self, module_name):
|
||||||
self.module_name = module_name
|
self.module_name = module_name
|
||||||
self.dictionaries_dir = []
|
self.dictionaries_dir = []
|
||||||
self.functions_file = []
|
self.functions_file = [func.__file__]
|
||||||
self.templates_dir = []
|
self.templates_dir = []
|
||||||
self.patches_dir = []
|
self.patches_dir = []
|
||||||
self.extra_dictionaries = {}
|
self.extra_dictionaries = {}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
from .utils import MULTI_FUNCTIONS, load_zones, value_pprint, RISOTTO_CONFIG, EXTRA_ANNOTATORS, ROUGAIL_NAMESPACE, ROUGAIL_NAMESPACE_DESCRIPTION
|
from .utils import MULTI_FUNCTIONS, load_zones, value_pprint, RISOTTO_CONFIG, EXTRA_ANNOTATORS, ROUGAIL_NAMESPACE, ROUGAIL_NAMESPACE_DESCRIPTION
|
||||||
from .image import Applications, Modules, valid_mandatories, applicationservice_copy
|
from .image import Applications, Modules, valid_mandatories, applicationservice_copy
|
||||||
from .rougail.annotator import calc_providers, calc_providers_global, calc_providers_dynamic, calc_providers_dynamic_follower, calc_providers_follower
|
|
||||||
|
|
||||||
from rougail import RougailConfig, RougailConvert
|
from rougail import RougailConfig, RougailConvert
|
||||||
from os import remove, makedirs, listdir, chmod
|
from os import remove, makedirs, listdir, chmod
|
||||||
|
|
@ -9,7 +8,7 @@ from pickle import dump as pickle_dump, load as pickle_load
|
||||||
from yaml import load as yaml_load, SafeLoader
|
from yaml import load as yaml_load, SafeLoader
|
||||||
from ipaddress import IPv4Interface, ip_network
|
from ipaddress import IPv4Interface, ip_network
|
||||||
#
|
#
|
||||||
from tiramisu import Config, valid_network_netmask, valid_ip_netmask, valid_broadcast, valid_in_network, valid_not_equal, calc_value, calc_value_property_help
|
from tiramisu import Config
|
||||||
from rougail.utils import normalize_family
|
from rougail.utils import normalize_family
|
||||||
from rougail import RougailSystemdTemplate
|
from rougail import RougailSystemdTemplate
|
||||||
from shutil import copy2, copytree, rmtree
|
from shutil import copy2, copytree, rmtree
|
||||||
|
|
@ -36,20 +35,6 @@ INSTALL_CONFIG_DIR = 'configurations'
|
||||||
INSTALL_TMPL_DIR= 'templates'
|
INSTALL_TMPL_DIR= 'templates'
|
||||||
INSTALL_IMAGES_DIR = 'images_files'
|
INSTALL_IMAGES_DIR = 'images_files'
|
||||||
INSTALL_TESTS_DIR = 'tests'
|
INSTALL_TESTS_DIR = 'tests'
|
||||||
FUNCTIONS = {'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,
|
|
||||||
'valid_network_netmask': valid_network_netmask,
|
|
||||||
'valid_ip_netmask': valid_ip_netmask,
|
|
||||||
'valid_broadcast': valid_broadcast,
|
|
||||||
'valid_in_network': valid_in_network,
|
|
||||||
'valid_not_equal': valid_not_equal,
|
|
||||||
'calc_value': calc_value,
|
|
||||||
'calc_value_property_help': calc_value_property_help,
|
|
||||||
'normalize_family': normalize_family,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def copy(src_file, dst_file):
|
def copy(src_file, dst_file):
|
||||||
|
|
@ -201,7 +186,6 @@ class Loader:
|
||||||
cfg['variable_namespace_description'] = ROUGAIL_NAMESPACE_DESCRIPTION
|
cfg['variable_namespace_description'] = ROUGAIL_NAMESPACE_DESCRIPTION
|
||||||
cfg['multi_functions'] = MULTI_FUNCTIONS
|
cfg['multi_functions'] = MULTI_FUNCTIONS
|
||||||
cfg['extra_annotators'] = EXTRA_ANNOTATORS
|
cfg['extra_annotators'] = EXTRA_ANNOTATORS
|
||||||
cfg['internal_functions'] = list(FUNCTIONS.keys())
|
|
||||||
cfg['force_convert_dyn_option_description'] = True
|
cfg['force_convert_dyn_option_description'] = True
|
||||||
cfg['risotto_globals'] = {}
|
cfg['risotto_globals'] = {}
|
||||||
|
|
||||||
|
|
@ -267,6 +251,7 @@ class Loader:
|
||||||
self.zones[zone_name] = {'domain_name': zone_domaine_name,
|
self.zones[zone_name] = {'domain_name': zone_domaine_name,
|
||||||
'network': str(sub_network),
|
'network': str(sub_network),
|
||||||
'host_ip': str(network + 1),
|
'host_ip': str(network + 1),
|
||||||
|
'host_name': host_name.split('.', 1)[0],
|
||||||
'length': length,
|
'length': length,
|
||||||
'start_ip': str(network + 2)
|
'start_ip': str(network + 2)
|
||||||
}
|
}
|
||||||
|
|
@ -289,8 +274,10 @@ class Loader:
|
||||||
# load host
|
# load host
|
||||||
module_info = modules.get('host')
|
module_info = modules.get('host')
|
||||||
tls_host_name = f'{server_name}.{self.zones[list(self.zones)[0]]["domain_name"]}'
|
tls_host_name = f'{server_name}.{self.zones[list(self.zones)[0]]["domain_name"]}'
|
||||||
|
short_host_name = host_name.split('.', 1)[0]
|
||||||
|
values = [f'{short_host_name}.{self.zones[zone_name]["domain_name"]}' for zone_name in zones_name]
|
||||||
cfg['risotto_globals'][host_name] = {'global:server_name': host_name,
|
cfg['risotto_globals'][host_name] = {'global:server_name': host_name,
|
||||||
'global:server_names': [host_name for zone in self.zones],
|
'global:server_names': values,
|
||||||
'global:zones_name': list(self.zones),
|
'global:zones_name': list(self.zones),
|
||||||
'global:module_name': 'host',
|
'global:module_name': 'host',
|
||||||
'global:host_install_dir': abspath(INSTALL_DIR),
|
'global:host_install_dir': abspath(INSTALL_DIR),
|
||||||
|
|
@ -333,6 +320,16 @@ class Loader:
|
||||||
self.modules[host_name] = modules_info
|
self.modules[host_name] = modules_info
|
||||||
cfg['functions_file'] = list(functions_files)
|
cfg['functions_file'] = list(functions_files)
|
||||||
self.tiram_obj = rougail.save(TIRAMISU_CACHE)
|
self.tiram_obj = rougail.save(TIRAMISU_CACHE)
|
||||||
|
with open(TIRAMISU_CACHE, 'a') as cache:
|
||||||
|
cache.write(f"""#from pickle import load
|
||||||
|
#config = Config(option_0)
|
||||||
|
#config.property.read_only()
|
||||||
|
#with open('{VALUES_CACHE}', 'rb') as fh:
|
||||||
|
# config.value.importation(load(fh))
|
||||||
|
#with open('{INFORMATIONS_CACHE}', 'rb') as fh:
|
||||||
|
# config.information.importation(load(fh))
|
||||||
|
#print(config.value.mandatory())
|
||||||
|
""")
|
||||||
|
|
||||||
def add_tls(self):
|
def add_tls(self):
|
||||||
zones = set()
|
zones = set()
|
||||||
|
|
@ -373,12 +370,11 @@ class Loader:
|
||||||
|
|
||||||
def tiramisu_file_to_tiramisu(self):
|
def tiramisu_file_to_tiramisu(self):
|
||||||
# l
|
# l
|
||||||
tiramisu_space = FUNCTIONS.copy()
|
tiramisu_space = {}
|
||||||
try:
|
try:
|
||||||
exec(self.tiram_obj, None, tiramisu_space)
|
exec(self.tiram_obj, None, tiramisu_space)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(self.tiram_obj)
|
raise Exception(f'unknown error when load tiramisu object: "{err}" see the file "{TIRAMISU_CACHE}" for more details') from err
|
||||||
raise Exception(f'unknown error when load tiramisu object {err}') from err
|
|
||||||
if self.original_display_name:
|
if self.original_display_name:
|
||||||
display_name = None
|
display_name = None
|
||||||
else:
|
else:
|
||||||
|
|
@ -416,6 +412,10 @@ class Loader:
|
||||||
# FIXME only one host_name is supported
|
# FIXME only one host_name is supported
|
||||||
config.information.set('modules', self.modules[host_name])
|
config.information.set('modules', self.modules[host_name])
|
||||||
# config.information.set('modules', {module_name: module_info.depends for module_name, module_info in self.module_infos.items() if module_name in modules})
|
# config.information.set('modules', {module_name: module_info.depends for module_name, module_info in self.module_infos.items() if module_name in modules})
|
||||||
|
with open(VALUES_CACHE, 'wb') as fh:
|
||||||
|
pickle_dump(config.value.exportation(), fh)
|
||||||
|
with open(INFORMATIONS_CACHE, 'wb') as fh:
|
||||||
|
pickle_dump(config.information.exportation(), fh)
|
||||||
config.property.add('cache')
|
config.property.add('cache')
|
||||||
if self.valid_mandatories:
|
if self.valid_mandatories:
|
||||||
messages = valid_mandatories(config)
|
messages = valid_mandatories(config)
|
||||||
|
|
@ -426,10 +426,6 @@ class Loader:
|
||||||
msg += '\n'.join(variables)
|
msg += '\n'.join(variables)
|
||||||
raise Exception(msg)
|
raise Exception(msg)
|
||||||
config.property.read_only()
|
config.property.read_only()
|
||||||
with open(VALUES_CACHE, 'wb') as fh:
|
|
||||||
pickle_dump(config.value.exportation(), fh)
|
|
||||||
with open(INFORMATIONS_CACHE, 'wb') as fh:
|
|
||||||
pickle_dump(config.information.exportation(), fh)
|
|
||||||
|
|
||||||
def set_values(self,
|
def set_values(self,
|
||||||
server_name,
|
server_name,
|
||||||
|
|
|
||||||
|
|
@ -1,136 +1,9 @@
|
||||||
from rougail.annotator.variable import Walk
|
from rougail.annotator.variable import Walk
|
||||||
from rougail.error import DictConsistencyError
|
from rougail.error import DictConsistencyError
|
||||||
from risotto.utils import _, multi_function
|
from rougail.utils import normalize_family
|
||||||
|
from risotto.utils import _
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
def _parse_kwargs(provider, dns, kwargs, index=None):
|
|
||||||
if not isinstance(dns, list):
|
|
||||||
raise Exception('pfff')
|
|
||||||
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:
|
|
||||||
continue
|
|
||||||
if isinstance(data['dns'], list):
|
|
||||||
for ddns in data['dns']:
|
|
||||||
if ddns in dns:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
elif data['dns'] not in dns:
|
|
||||||
continue
|
|
||||||
# del data['dns']
|
|
||||||
yield data
|
|
||||||
|
|
||||||
|
|
||||||
@multi_function
|
|
||||||
def calc_providers_global(provider, multi, unique, value, suffix=None):
|
|
||||||
if suffix is not None:
|
|
||||||
return value[int(suffix)]
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
@multi_function
|
|
||||||
def calc_providers_follower(provider, multi, unique, 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, unique, 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, unique, 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 not unique or 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, unique, dns, **kwargs):
|
|
||||||
ret = []
|
|
||||||
for data in _parse_kwargs(provider, dns, kwargs):
|
|
||||||
if isinstance(data['value'], list):
|
|
||||||
commun_dns = list(set(data['dns']) & set(dns))
|
|
||||||
if len(commun_dns) == 1:
|
|
||||||
ret.append(data['value'][data['dns'].index(commun_dns[0])])
|
|
||||||
continue
|
|
||||||
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):
|
class Annotator(Walk):
|
||||||
|
|
@ -138,290 +11,394 @@ class Annotator(Walk):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
objectspace: 'RougailObjSpace',
|
objectspace: 'RougailObjSpace',
|
||||||
*args):
|
*args):
|
||||||
self.objectspace = objectspace
|
|
||||||
self.get_suppliers_providers()
|
|
||||||
self.dispatch_provider_supplier_to_zones()
|
|
||||||
self.dispatch_provider_to_zones()
|
|
||||||
self.convert_providers()
|
|
||||||
self.convert_suppliers()
|
|
||||||
|
|
||||||
def get_suppliers_providers(self) -> None:
|
|
||||||
""" get supplier informations
|
|
||||||
return something like:
|
|
||||||
{'Host': ['host1.example.net', 'host2.example.net']}
|
|
||||||
"""
|
|
||||||
self.suppliers = {}
|
|
||||||
self.providers = {}
|
self.providers = {}
|
||||||
|
self.suppliers = {}
|
||||||
|
self.globals = {}
|
||||||
|
self.provider_links = {}
|
||||||
|
self.providers_zone = {}
|
||||||
|
self.provider_maps = {}
|
||||||
|
self.objectspace = objectspace
|
||||||
|
#
|
||||||
|
self.get_providers_suppliers()
|
||||||
|
self.get_provider_links()
|
||||||
|
self.get_provider_maps()
|
||||||
|
self.convert_providers()
|
||||||
|
self.convert_globals()
|
||||||
|
|
||||||
|
def get_providers_suppliers(self) -> None:
|
||||||
|
"""parse all variable and get provider and supplier informations
|
||||||
|
"""
|
||||||
for variable in self.get_variables():
|
for variable in self.get_variables():
|
||||||
if not hasattr(variable, 'supplier') and not hasattr(variable, 'provider'):
|
for type_ in 'provider', 'supplier':
|
||||||
continue
|
if hasattr(variable, type_):
|
||||||
nf_dns = variable.path.split('.', 1)[0]
|
provider_name = getattr(variable, type_)
|
||||||
server_name = self.objectspace.space.variables[nf_dns].doc
|
# add information with provider/supplier name
|
||||||
# supplier
|
|
||||||
if hasattr(variable, 'supplier') and ':' not in variable.supplier:
|
|
||||||
server_names = self.objectspace.rougailconfig['risotto_globals'][server_name]['global:server_names']
|
|
||||||
zones = self.objectspace.rougailconfig['risotto_globals'][server_name]['global:zones_name']
|
|
||||||
s_data = {'option': variable,
|
|
||||||
'dns': server_name,
|
|
||||||
'path_prefix': nf_dns,
|
|
||||||
'server_names': server_names,
|
|
||||||
'zones': zones,
|
|
||||||
'providers_zone': {},
|
|
||||||
}
|
|
||||||
if variable.supplier != 'Host' and not variable.supplier.startswith('Host:') and not variable.supplier.startswith('global:'):
|
|
||||||
if 'global:provider_zone' in self.objectspace.rougailconfig['risotto_globals'][server_name]:
|
|
||||||
s_data['provider_zone'] = self.objectspace.rougailconfig['risotto_globals'][server_name]['global:provider_zone']
|
|
||||||
self.suppliers.setdefault(variable.supplier, []).append(s_data)
|
|
||||||
if not hasattr(variable, 'information'):
|
if not hasattr(variable, 'information'):
|
||||||
variable.information = self.objectspace.information(variable.xmlfiles)
|
variable.information = self.objectspace.information(variable.xmlfiles)
|
||||||
variable.information.supplier = variable.supplier
|
setattr(variable.information, type_, provider_name)
|
||||||
# provider
|
|
||||||
if hasattr(variable, 'provider'):
|
# construct self.globals, self.suppliers and self.providers dictionnaries
|
||||||
provider_name = variable.provider
|
provider_prefix, provider_suffix = self._cut_out_provider_name(provider_name)
|
||||||
p_data = {'option': variable,
|
dns = self.objectspace.space.variables[variable.path_prefix].doc
|
||||||
'dns': server_name,
|
if provider_prefix == 'global':
|
||||||
'provider_name': provider_name,
|
if type_ == 'supplier':
|
||||||
'path_prefix': nf_dns,
|
raise DictConsistencyError(f'{type_} {provider_name} in {dns} not allowed', 0, variable.xmlfiles)
|
||||||
'suppliers_zone': {},
|
obj = self.globals
|
||||||
}
|
elif type_ == 'supplier':
|
||||||
if variable.provider != 'Host' and not variable.provider.startswith('Host:') and not variable.provider.startswith('global:'):
|
obj = self.suppliers
|
||||||
if 'global:provider_zone' in self.objectspace.rougailconfig['risotto_globals'][server_name]:
|
|
||||||
p_data['provider_zone'] = self.objectspace.rougailconfig['risotto_globals'][server_name]['global:provider_zone']
|
|
||||||
if self.objectspace.rougailconfig['risotto_globals'][server_name]['global:module_name'] == 'host':
|
|
||||||
server_names = [server_name]
|
|
||||||
else:
|
else:
|
||||||
server_names = self.objectspace.rougailconfig['risotto_globals'][server_name]['global:server_names']
|
obj = self.providers
|
||||||
p_data['server_names'] = server_names
|
sub_obj = obj.setdefault(provider_prefix, {}).setdefault(dns, {})
|
||||||
if self.objectspace.rougailconfig['risotto_globals'][server_name]['global:module_name'] != 'host':
|
if provider_suffix in sub_obj:
|
||||||
p_data['zones'] = self.objectspace.rougailconfig['risotto_globals'][server_name]['global:zones_name']
|
raise DictConsistencyError(f'multiple {type_} {provider_name} in {dns}', 0, sub_obj[provider_suffix].xmlfiles + variable.xmlfiles)
|
||||||
|
sub_obj[provider_suffix] = variable
|
||||||
|
|
||||||
|
def _cut_out_provider_name(self,
|
||||||
|
provider_name: str,
|
||||||
|
) -> Tuple[str, str]:
|
||||||
|
"""get provider_name and return provider_prefix and provider_suffix
|
||||||
|
"""
|
||||||
if ':' in provider_name:
|
if ':' in provider_name:
|
||||||
p_data['is_main_provider'] = False
|
provider_prefix, provider_suffix = provider_name.split(':', 1)
|
||||||
provider = provider_name.rsplit(':', 1)[0]
|
|
||||||
else:
|
else:
|
||||||
p_data['is_main_provider'] = True
|
provider_prefix = provider_name
|
||||||
provider = variable.provider
|
provider_suffix = None
|
||||||
self.providers.setdefault(provider, []).append(p_data)
|
return provider_prefix, provider_suffix
|
||||||
|
|
||||||
def dispatch_provider_supplier_to_zones(self):
|
def get_provider_links(self):
|
||||||
"""calculate zone where provider and supplier communicate
|
"""Search link between providers
|
||||||
|
'ProviderPrefix': {'provider_dns': ['supplier_dns_1',
|
||||||
|
'supplier_dns_2',
|
||||||
|
'supplier_dns_3']}
|
||||||
"""
|
"""
|
||||||
self.providers_zone = {}
|
for provider_prefix, providers_dns in self.providers.items():
|
||||||
for provider_name, p_datas in self.providers.items():
|
self.provider_links[provider_prefix] = {}
|
||||||
for p_data in p_datas:
|
for provider_dns, providers_suffix in providers_dns.items():
|
||||||
if provider_name in ['global', 'Host'] or provider_name not in self.suppliers:
|
if None not in providers_suffix:
|
||||||
|
# it's a reverse provider!
|
||||||
continue
|
continue
|
||||||
if not 'provider_zone' in p_data:
|
if provider_prefix != 'Host':
|
||||||
provider_zone = None
|
provider_zone = self.objectspace.rougailconfig['risotto_globals'][provider_dns]['global:provider_zone']
|
||||||
else:
|
if provider_prefix not in self.suppliers:
|
||||||
provider_zone = p_data['provider_zone']
|
|
||||||
for s_data in self.suppliers[provider_name]:
|
|
||||||
if not provider_zone:
|
|
||||||
if provider_name.endswith('Client'):
|
|
||||||
p_server = provider_name[0:-6]
|
|
||||||
if p_server not in self.providers:
|
|
||||||
continue
|
continue
|
||||||
for p_data_t in self.providers[p_server]:
|
for supplier_dns, suppliers_suffix in self.suppliers[provider_prefix].items():
|
||||||
if p_data_t['dns'] == s_data['dns'] and 'provider_zone' in p_data_t:
|
if provider_dns == supplier_dns:
|
||||||
zone = p_data_t['provider_zone']
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
continue
|
continue
|
||||||
else:
|
if provider_prefix == 'Host':
|
||||||
|
provider_zone = self.objectspace.rougailconfig['risotto_globals'][supplier_dns]['global:zones_name'][0]
|
||||||
|
if provider_zone not in self.objectspace.rougailconfig['risotto_globals'][supplier_dns]['global:zones_name']:
|
||||||
continue
|
continue
|
||||||
else:
|
self.provider_links[provider_prefix].setdefault(provider_dns, []).append(supplier_dns)
|
||||||
zone = provider_zone
|
|
||||||
if zone not in s_data['zones']:
|
|
||||||
continue
|
|
||||||
s_data['providers_zone'][provider_name] = zone
|
|
||||||
p_data['suppliers_zone'].setdefault(provider_name, {})[s_data['dns']] = zone
|
|
||||||
self.providers_zone.setdefault(zone, set()).add(provider_name)
|
|
||||||
|
|
||||||
def dispatch_provider_to_zones(self):
|
def get_provider_maps(self):
|
||||||
""" add information with provider zone domain name
|
"""relation between provider_prefix and provider_suffix
|
||||||
|
'provider_prefix': {'normal': {None, 'provider_suffix_1', 'provider_suffix_2'},
|
||||||
|
'reverse': {'provider_suffix_3', 'provider_suffix_4'}}
|
||||||
"""
|
"""
|
||||||
self.providers_zone = {}
|
for provider_prefix, providers_dns in self.provider_links.items():
|
||||||
for provider_name, p_datas in self.providers.items():
|
self.provider_maps[provider_prefix] = {'normal': set(), 'reverse': set()}
|
||||||
for p_data in p_datas:
|
for provider_dns, suppliers_dns in providers_dns.items():
|
||||||
if provider_name in ['global', 'Host'] or provider_name not in self.suppliers:
|
for supplier_dns in suppliers_dns:
|
||||||
|
if supplier_dns in self.providers[provider_prefix] and None in self.providers[provider_prefix][supplier_dns]:
|
||||||
|
#exists?
|
||||||
continue
|
continue
|
||||||
if not 'provider_zone' in p_data:
|
# get prefixes
|
||||||
|
prefixes = set(self.providers[provider_prefix][provider_dns]) & set(self.suppliers[provider_prefix][supplier_dns])
|
||||||
|
self.provider_maps[provider_prefix]['normal'] |= prefixes
|
||||||
|
# get suffixes
|
||||||
|
if supplier_dns not in self.providers[provider_prefix]:
|
||||||
continue
|
continue
|
||||||
provider_zone = p_data['provider_zone']
|
suffixes = set(self.providers[provider_prefix][supplier_dns]) & set(self.suppliers[provider_prefix][provider_dns])
|
||||||
family = self.objectspace.paths.get_variable(f"providers",
|
self.provider_maps[provider_prefix]['reverse'] |= suffixes
|
||||||
namespace=self.objectspace.rougailconfig['variable_namespace'],
|
|
||||||
force_path_prefix=p_data['path_prefix'],
|
def convert_providers(self) -> None:
|
||||||
|
"""Convert providers informations to default values or fills
|
||||||
|
"""
|
||||||
|
for provider_prefix, providers_dns in self.provider_links.items():
|
||||||
|
for provider_dns, suppliers_dns in providers_dns.items():
|
||||||
|
for provider_suffix in self.provider_maps[provider_prefix]['normal']:
|
||||||
|
self._convert_providers_normal(provider_prefix,
|
||||||
|
provider_suffix,
|
||||||
|
provider_dns,
|
||||||
|
suppliers_dns,
|
||||||
|
)
|
||||||
|
for provider_suffix in self.provider_maps[provider_prefix]['reverse']:
|
||||||
|
self._convert_providers_reverse(provider_prefix,
|
||||||
|
provider_suffix,
|
||||||
|
provider_dns,
|
||||||
|
suppliers_dns,
|
||||||
)
|
)
|
||||||
if not hasattr(family, 'information'):
|
|
||||||
family.information = self.objectspace.information(family.xmlfiles)
|
|
||||||
name_in_zone = p_data['server_names'][p_data['zones'].index(provider_zone)]
|
|
||||||
setattr(family.information, provider_name, name_in_zone)
|
|
||||||
setattr(family.information, f'{provider_name}:zone', provider_zone)
|
|
||||||
|
|
||||||
def convert_providers(self):
|
def _convert_providers_normal(self,
|
||||||
for provider_name, providers_data in self.providers.items():
|
provider_prefix: str,
|
||||||
for provider_data in providers_data:
|
provider_suffix: str,
|
||||||
if provider_name != 'global' and provider_name not in self.suppliers:
|
provider_dns: str,
|
||||||
|
suppliers_dns: dict,
|
||||||
|
) -> None:
|
||||||
|
if provider_prefix != 'Host':
|
||||||
|
provider_zone = self.objectspace.rougailconfig['risotto_globals'][provider_dns]['global:provider_zone']
|
||||||
|
provider_option_dns = self._get_dns_from_provider_zone(provider_dns, provider_zone)
|
||||||
|
variable = self.providers[provider_prefix][provider_dns][provider_suffix]
|
||||||
|
if hasattr(variable, 'value'):
|
||||||
|
raise DictConsistencyError(f'variable {variable.path} has a provider and a value', 0, variable.xmlfiles)
|
||||||
|
suppliers_var = {}
|
||||||
|
for supplier_dns in suppliers_dns:
|
||||||
|
if provider_suffix not in self.suppliers[provider_prefix][supplier_dns]:
|
||||||
continue
|
continue
|
||||||
# create a fill for this variable
|
if provider_prefix == 'Host':
|
||||||
variable = provider_data['option']
|
provider_zone = self.objectspace.rougailconfig['risotto_globals'][supplier_dns]['global:zones_name'][0]
|
||||||
|
provider_option_dns = self._get_dns_from_provider_zone(provider_dns, provider_zone)
|
||||||
|
supplier_variable = self.suppliers[provider_prefix][supplier_dns][provider_suffix]
|
||||||
|
supplier_option_dns = self._get_dns_from_provider_zone(supplier_dns, provider_zone)
|
||||||
|
suppliers_var[supplier_option_dns] = supplier_variable
|
||||||
|
if provider_suffix:
|
||||||
|
AddFill(self.objectspace,
|
||||||
|
provider_prefix,
|
||||||
|
provider_suffix,
|
||||||
|
provider_option_dns,
|
||||||
|
variable,
|
||||||
|
suppliers_var,
|
||||||
|
False,
|
||||||
|
supplier_variable.path_prefix,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._set_provider_supplier(provider_option_dns,
|
||||||
|
variable,
|
||||||
|
suppliers_var,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _convert_providers_reverse(self,
|
||||||
|
provider_prefix: str,
|
||||||
|
provider_suffix: str,
|
||||||
|
provider_dns: str,
|
||||||
|
suppliers_dns: dict,
|
||||||
|
) -> None:
|
||||||
|
if provider_prefix != 'Host':
|
||||||
|
provider_zone = self.objectspace.rougailconfig['risotto_globals'][provider_dns]['global:provider_zone']
|
||||||
|
provider_option_dns = self._get_dns_from_provider_zone(provider_dns, provider_zone)
|
||||||
|
variable = self.suppliers[provider_prefix][provider_dns][provider_suffix]
|
||||||
|
if hasattr(variable, 'value'):
|
||||||
|
raise DictConsistencyError(f'variable {variable.path} has a provider and a value', 0, variable.xmlfiles)
|
||||||
|
for supplier_dns in suppliers_dns:
|
||||||
|
if provider_prefix == 'Host':
|
||||||
|
provider_zone = self.objectspace.rougailconfig['risotto_globals'][supplier_dns]['global:zones_name'][0]
|
||||||
|
provider_option_dns = self._get_dns_from_provider_zone(provider_dns, provider_zone)
|
||||||
|
supplier_variable = self.providers[provider_prefix][supplier_dns][provider_suffix]
|
||||||
|
supplier_option_dns = self._get_dns_from_provider_zone(supplier_dns, provider_zone)
|
||||||
|
AddFill(self.objectspace,
|
||||||
|
provider_prefix,
|
||||||
|
provider_suffix,
|
||||||
|
supplier_option_dns,
|
||||||
|
supplier_variable,
|
||||||
|
{provider_option_dns: variable},
|
||||||
|
True,
|
||||||
|
supplier_variable.path_prefix,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_dns_from_provider_zone(self,
|
||||||
|
dns,
|
||||||
|
zone,
|
||||||
|
) -> str:
|
||||||
|
risotto_global = self.objectspace.rougailconfig['risotto_globals'][dns]
|
||||||
|
index = risotto_global['global:zones_name'].index(zone)
|
||||||
|
return risotto_global['global:server_names'][index]
|
||||||
|
|
||||||
|
def _set_provider_supplier(self,
|
||||||
|
provider_dns: str,
|
||||||
|
variable,
|
||||||
|
suppliers,
|
||||||
|
) -> None:
|
||||||
|
# suffix is None so not a client and there only one provider
|
||||||
|
# the value of this variable is the list of suppliers DNS name
|
||||||
|
if not variable.multi:
|
||||||
|
raise DictConsistencyError(f'"{variable.name}" is a provider and must be a multi', 0, variable.xmlfiles)
|
||||||
|
variable.default = list(suppliers)
|
||||||
|
# suffix is None so the supplier values are provider DNS
|
||||||
|
for sub_variable in suppliers.values():
|
||||||
|
#FIXME
|
||||||
|
#if hasattr(option, 'value'):
|
||||||
|
# raise DictConsistencyError(f'"{option.name}" is a supplier and cannot have value', 0, option.xmlfiles)
|
||||||
|
if sub_variable.multi:
|
||||||
|
raise DictConsistencyError(f'"{sub_variable.name}" is a supplier and mustnot be a multi', 0, sub_variable.xmlfiles)
|
||||||
|
sub_variable.default = provider_dns
|
||||||
|
|
||||||
|
def convert_globals(self):
|
||||||
|
"""Convert providers global informations to default values or fills
|
||||||
|
"""
|
||||||
|
provider_prefix = 'global'
|
||||||
|
for provider_dns, providers_suffix in self.globals[provider_prefix].items():
|
||||||
|
for provider_suffix, variable in providers_suffix.items():
|
||||||
|
provider_name = f'{provider_prefix}:{provider_suffix}'
|
||||||
|
if provider_name not in self.objectspace.rougailconfig['risotto_globals'][provider_dns]:
|
||||||
|
raise DictConsistencyError(f'cannot find {provider_name} for variable {variable.path}, should be in {list(self.objectspace.rougailconfig["risotto_globals"][provider_dns])}', 0, variable.xmlfiles)
|
||||||
|
provider_values = self.objectspace.rougailconfig['risotto_globals'][provider_dns][provider_name]
|
||||||
|
if isinstance(provider_values, list) and self.objectspace.paths.is_dynamic(variable):
|
||||||
|
if variable.multi:
|
||||||
|
raise DictConsistencyError(f'variable {variable.path} has provider {provider_name} and is in dynamic family so must not be a multi', 0, variable.xmlfiles)
|
||||||
|
self._set_global_dynamic_option(variable, provider_values)
|
||||||
|
else:
|
||||||
|
if isinstance(provider_values, list) and not variable.multi:
|
||||||
|
raise DictConsistencyError(f'variable {variable.path} has provider {provider_name} which is a multi', 0, variable.xmlfiles)
|
||||||
|
if not isinstance(provider_values, list):
|
||||||
|
if variable.multi:
|
||||||
|
raise DictConsistencyError(f'variable {variable.path} has provider {provider_name} which is not a multi', 0, variable.xmlfiles)
|
||||||
|
provider_values = [provider_values]
|
||||||
|
|
||||||
|
variable.value = []
|
||||||
|
for provider_value in provider_values:
|
||||||
|
value = self.objectspace.value(variable.xmlfiles)
|
||||||
|
value.name = provider_value
|
||||||
|
if isinstance(provider_value, bool):
|
||||||
|
value.type = 'boolean'
|
||||||
|
variable.value.append(value)
|
||||||
|
|
||||||
|
def _set_global_dynamic_option(self,
|
||||||
|
variable: 'self.objectspace.Variable',
|
||||||
|
values: List[str],
|
||||||
|
):
|
||||||
fill = self.objectspace.fill(variable.xmlfiles)
|
fill = self.objectspace.fill(variable.xmlfiles)
|
||||||
new_target = self.objectspace.target(variable.xmlfiles)
|
new_target = self.objectspace.target(variable.xmlfiles)
|
||||||
new_target.name = variable
|
new_target.name = variable.name
|
||||||
fill.target = [new_target]
|
fill.target = [new_target]
|
||||||
if provider_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.namespace = variable.namespace
|
||||||
fill.index = 0
|
fill.index = 0
|
||||||
# first parameter: the provider name (something link Host:incoming_ports)
|
fill.name = 'risotto_providers_global'
|
||||||
param = self.objectspace.param(variable.xmlfiles)
|
param1 = self.objectspace.param(variable.xmlfiles)
|
||||||
param.name = 'provider'
|
param1.text = values
|
||||||
param.text = provider_data['provider_name']
|
param2 = self.objectspace.param(variable.xmlfiles)
|
||||||
fill.param = [param]
|
param2.type = 'suffix'
|
||||||
# second parameter: current variable is a multi variable?
|
fill.param = [param1, param2]
|
||||||
param = self.objectspace.param(variable.xmlfiles)
|
if not hasattr(self.objectspace.space.variables[variable.path_prefix].constraints, 'fill'):
|
||||||
param.name = 'multi'
|
self.objectspace.space.variables[variable.path_prefix].constraints.fill = []
|
||||||
param.text = variable.multi
|
self.objectspace.space.variables[variable.path_prefix].constraints.fill.append(fill)
|
||||||
param.type = 'boolean'
|
|
||||||
fill.param.append(param)
|
|
||||||
#
|
|
||||||
param = self.objectspace.param(variable.xmlfiles)
|
|
||||||
param.name = 'unique'
|
|
||||||
param.text = variable.unique != "False"
|
|
||||||
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 provider_name != 'global':
|
|
||||||
param = self.objectspace.param(variable.xmlfiles)
|
|
||||||
param.name = 'dns'
|
|
||||||
param.text = provider_data['server_names']
|
|
||||||
fill.param.append(param)
|
|
||||||
if provider_name == 'global':
|
|
||||||
param = self.objectspace.param(variable.xmlfiles)
|
|
||||||
param.name = 'value'
|
|
||||||
if provider_data['provider_name'] in self.objectspace.rougailconfig['risotto_globals'][provider_data['dns']]:
|
|
||||||
value = self.objectspace.rougailconfig['risotto_globals'][provider_data['dns']][provider_data['provider_name']]
|
|
||||||
param.text = value
|
|
||||||
if isinstance(value, bool):
|
|
||||||
param.type = 'boolean'
|
|
||||||
else:
|
|
||||||
param.text = provider_data['provider_name']
|
|
||||||
param.type = 'information'
|
|
||||||
fill.param.append(param)
|
|
||||||
else:
|
|
||||||
# parse all supplier link to current provider
|
|
||||||
for idx, data in enumerate(self.suppliers[provider_name]):
|
|
||||||
if 'zones' in provider_data:
|
|
||||||
if provider_name not in data['providers_zone']:
|
|
||||||
continue
|
|
||||||
zone = data['providers_zone'][provider_name]
|
|
||||||
zidx = data['zones'].index(zone)
|
|
||||||
dns = data['server_names'][zidx]
|
|
||||||
else:
|
|
||||||
dns = data['dns']
|
|
||||||
option = data['option']
|
|
||||||
# if not provider, get the true option that we want have value
|
|
||||||
if not provider_data['is_main_provider']:
|
|
||||||
path_prefix = data['path_prefix']
|
|
||||||
try:
|
|
||||||
supplier_option = self.objectspace.paths.get_supplier(f'supplier:{provider_data["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 provider_data['is_main_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 provider_data['is_main_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[provider_data['path_prefix']], 'constraints'):
|
|
||||||
self.objectspace.space.variables[provider_data['path_prefix']].constraints = self.objectspace.constraints(None)
|
|
||||||
if not hasattr(self.objectspace.space.variables[provider_data['path_prefix']].constraints, 'fill'):
|
|
||||||
self.objectspace.space.variables[provider_data['path_prefix']].constraints.fill = []
|
|
||||||
self.objectspace.space.variables[provider_data['path_prefix']].constraints.fill.append(fill)
|
|
||||||
|
|
||||||
def convert_suppliers(self):
|
|
||||||
for supplier_name, s_datas in self.suppliers.items():
|
class AddFill:
|
||||||
if supplier_name == 'Host':
|
"""Add fill for variable
|
||||||
continue
|
"""
|
||||||
for s_data in s_datas:
|
def __init__(self,
|
||||||
if supplier_name not in self.providers:
|
objectspace,
|
||||||
continue
|
provider_prefix,
|
||||||
for p_data in self.providers[supplier_name]:
|
provider_suffix,
|
||||||
if s_data['dns'] == p_data['dns']:
|
provider_dns,
|
||||||
# supplier and provider are in same machine
|
variable,
|
||||||
continue
|
suppliers,
|
||||||
if supplier_name not in p_data['suppliers_zone'] or s_data['dns'] not in p_data['suppliers_zone'][supplier_name]:
|
reverse,
|
||||||
continue
|
path_prefix,
|
||||||
# get the DNS name in supplier zone
|
) -> None:
|
||||||
zone = p_data['suppliers_zone'][supplier_name][s_data['dns']]
|
self.objectspace = objectspace
|
||||||
if zone not in p_data['zones']:
|
self.provider_dns = provider_dns
|
||||||
continue
|
self.variable = variable
|
||||||
zidx = p_data['zones'].index(zone)
|
self.path_prefix = path_prefix
|
||||||
dns = p_data['server_names'][zidx]
|
self.suppliers = suppliers
|
||||||
new_value = self.objectspace.value(None)
|
self.create_fill()
|
||||||
new_value.name = dns
|
if reverse:
|
||||||
s_data['option'].value = [new_value]
|
self.param_reverse()
|
||||||
break
|
else:
|
||||||
|
if self.objectspace.paths.is_dynamic(self.variable):
|
||||||
|
self.param_dynamic()
|
||||||
|
elif self.variable.multi:
|
||||||
|
self.param_multi()
|
||||||
|
else:
|
||||||
|
provider_name = f'{provider_prefix}:{provider_suffix}'
|
||||||
|
raise DictConsistencyError(f'provider "{provider_name}" options must be in dynamic option or must be a multiple', 0, self.variable.xmlfiles)
|
||||||
|
if self.objectspace.paths.is_follower(self.variable):
|
||||||
|
self.param_follower()
|
||||||
|
self.end()
|
||||||
|
|
||||||
|
def create_fill(self) -> None:
|
||||||
|
self.fill = self.objectspace.fill(self.variable.xmlfiles)
|
||||||
|
new_target = self.objectspace.target(self.variable.xmlfiles)
|
||||||
|
new_target.name = self.variable
|
||||||
|
self.fill.target = [new_target]
|
||||||
|
self.fill.namespace = self.variable.namespace
|
||||||
|
self.fill.index = 0
|
||||||
|
self.fill.param = []
|
||||||
|
|
||||||
|
def param_reverse(self) -> None:
|
||||||
|
self.fill.name = 'risotto_flatten_values_client'
|
||||||
|
#
|
||||||
|
if self.objectspace.paths.is_follower(self.variable):
|
||||||
|
multi = self.variable.multi is True
|
||||||
|
else:
|
||||||
|
multi = self.variable.multi is not False
|
||||||
|
param = self.objectspace.param(self.variable.xmlfiles)
|
||||||
|
param.text = multi
|
||||||
|
param.type = 'boolean'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
for dns, variable in self.suppliers.items():
|
||||||
|
param = self.objectspace.param(variable.xmlfiles)
|
||||||
|
param.text = variable
|
||||||
|
param.propertyerror = False
|
||||||
|
param.type = 'variable'
|
||||||
|
param.suffix = normalize_family(self.provider_dns)
|
||||||
|
namespace = variable.namespace
|
||||||
|
family_path = self.objectspace.paths.get_variable_family_path(param.text.path,
|
||||||
|
namespace,
|
||||||
|
force_path_prefix=self.variable.path_prefix,
|
||||||
|
)
|
||||||
|
param.family = self.objectspace.paths.get_family(family_path,
|
||||||
|
namespace,
|
||||||
|
self.variable.path_prefix,
|
||||||
|
)
|
||||||
|
self.fill.param.append(param)
|
||||||
|
|
||||||
|
def param_dynamic(self) -> None:
|
||||||
|
self.fill.name = 'risotto_dyn_values'
|
||||||
|
#
|
||||||
|
param = self.objectspace.param(self.variable.xmlfiles)
|
||||||
|
param.type = 'suffix'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
#
|
||||||
|
param = self.objectspace.param(self.variable.xmlfiles)
|
||||||
|
param.text = self.variable.unique != "False"
|
||||||
|
param.type = 'boolean'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
#
|
||||||
|
if self.objectspace.paths.is_follower(self.variable):
|
||||||
|
multi = self.variable.multi is True
|
||||||
|
else:
|
||||||
|
multi = self.variable.multi is not False
|
||||||
|
param = self.objectspace.param(self.variable.xmlfiles)
|
||||||
|
param.text = multi
|
||||||
|
param.type = 'boolean'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
for dns, variable in self.suppliers.items():
|
||||||
|
#
|
||||||
|
param = self.objectspace.param(variable.xmlfiles)
|
||||||
|
param.text = variable
|
||||||
|
param.name = normalize_family(dns)
|
||||||
|
param.propertyerror = False
|
||||||
|
param.type = 'variable'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
|
||||||
|
def param_multi(self) -> None:
|
||||||
|
self.fill.name = 'risotto_flatten_values'
|
||||||
|
#
|
||||||
|
if self.objectspace.paths.is_follower(self.variable):
|
||||||
|
multi = self.variable.multi is True
|
||||||
|
else:
|
||||||
|
multi = self.variable.multi is not False
|
||||||
|
param = self.objectspace.param(self.variable.xmlfiles)
|
||||||
|
param.text = multi
|
||||||
|
param.type = 'boolean'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
for dns, variable in self.suppliers.items():
|
||||||
|
param = self.objectspace.param(variable.xmlfiles)
|
||||||
|
param.text = variable
|
||||||
|
param.propertyerror = False
|
||||||
|
param.type = 'variable'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
|
||||||
|
def param_follower(self):
|
||||||
|
param = self.objectspace.param(self.variable.xmlfiles)
|
||||||
|
param.name = 'follower_index'
|
||||||
|
param.type = 'index'
|
||||||
|
self.fill.param.append(param)
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
if not hasattr(self.objectspace.space.variables[self.path_prefix], 'constraints'):
|
||||||
|
self.objectspace.space.variables[self.path_prefix].constraints = self.objectspace.constraints(None)
|
||||||
|
if not hasattr(self.objectspace.space.variables[self.path_prefix].constraints, 'fill'):
|
||||||
|
self.objectspace.space.variables[self.path_prefix].constraints.fill = []
|
||||||
|
self.objectspace.space.variables[self.path_prefix].constraints.fill.append(self.fill)
|
||||||
|
|
|
||||||
61
src/risotto/rougail/func.py
Normal file
61
src/risotto/rougail/func.py
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
from risotto.utils import multi_function as _multi_function
|
||||||
|
from rougail.utils import normalize_family
|
||||||
|
from tiramisu import valid_network_netmask, valid_ip_netmask, valid_broadcast, valid_in_network, valid_not_equal, calc_value, calc_value_property_help
|
||||||
|
|
||||||
|
|
||||||
|
@_multi_function
|
||||||
|
def risotto_providers_global(value, suffix=None):
|
||||||
|
if suffix is not None:
|
||||||
|
return value[int(suffix)]
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
@_multi_function
|
||||||
|
def risotto_flatten_values(multi, *args, follower_index=None):
|
||||||
|
values = []
|
||||||
|
#if follower_index is None:
|
||||||
|
# for arg in args:
|
||||||
|
# if isinstance(arg, list):
|
||||||
|
# values.extend(arg)
|
||||||
|
# else:
|
||||||
|
# values.append(arg)
|
||||||
|
#else:
|
||||||
|
values = args
|
||||||
|
if follower_index is not None and len(values) > follower_index:
|
||||||
|
values = values[follower_index]
|
||||||
|
elif not multi:
|
||||||
|
if not values:
|
||||||
|
values = None
|
||||||
|
if len(values) == 1:
|
||||||
|
values = values[0]
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
@_multi_function
|
||||||
|
def risotto_flatten_values_client(multi, *args):
|
||||||
|
values = []
|
||||||
|
for arg in args:
|
||||||
|
if isinstance(arg, list):
|
||||||
|
values.extend(arg)
|
||||||
|
else:
|
||||||
|
values.append(arg)
|
||||||
|
if not multi:
|
||||||
|
if not values:
|
||||||
|
values = None
|
||||||
|
if len(values) == 1:
|
||||||
|
values = values[0]
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
@_multi_function
|
||||||
|
def risotto_dyn_values(suffix, unique, multi, follower_index=None, **kwargs):
|
||||||
|
values = kwargs.get(normalize_family(suffix), [] if multi else None)
|
||||||
|
if not multi and follower_index is not None and isinstance(values, list) and len(values) > follower_index:
|
||||||
|
values = values[follower_index]
|
||||||
|
if isinstance(values, list) and unique:
|
||||||
|
values_ = []
|
||||||
|
for val in values:
|
||||||
|
if val not in values_:
|
||||||
|
values_.append(val)
|
||||||
|
values = values_
|
||||||
|
return values
|
||||||
Loading…
Reference in a new issue