Compare commits

...

17 Commits

Author SHA1 Message Date
b1eb050c8d Merge branch 'develop' into dist/risotto/risotto-2.8.0/develop 2021-05-24 08:38:26 +02:00
c6aed1043d force config_file creation if not exists 2021-05-24 08:38:05 +02:00
df6e783daf Merge branch 'develop' into dist/risotto/risotto-2.8.0/develop 2021-05-23 21:39:50 +02:00
c52586c570 nsd and unbound dataset 2021-05-23 21:39:44 +02:00
48934f5b6f Merge branch 'develop' into dist/risotto/risotto-2.8.0/develop 2021-05-22 18:07:24 +02:00
05af5b14ba add ouputter 2021-05-22 18:07:09 +02:00
55407ae133 Merge branch 'develop' into dist/risotto/risotto-2.8.0/develop 2021-05-22 16:39:48 +02:00
416bcfec7b add ouputter 2021-05-22 16:39:42 +02:00
addb90f6c3 update dataset 2021-05-18 19:04:24 +02:00
e961491e54 host.network => network 2021-05-16 06:59:19 +02:00
97f3250e2e memory is Mb size 2021-05-11 08:20:03 +02:00
326af0cd5c Merge branch 'develop' into dist/risotto/risotto-2.8.0/develop 2021-04-26 17:57:38 +02:00
9cf64d8238 cucchiaiata improvment 2021-04-26 17:57:31 +02:00
fbf4fc9643 Merge branch 'develop' into dist/risotto/risotto-2.8.0/develop 2021-04-24 12:57:14 +02:00
1b5ef5021e error is in json format 2021-04-24 12:57:07 +02:00
24ea05b64a Merge branch 'develop' into dist/risotto/risotto-2.8.0/develop 2021-04-24 10:21:44 +02:00
7fc109842d update example script 2021-04-24 10:21:31 +02:00
10 changed files with 264 additions and 105 deletions

View File

@ -2,22 +2,26 @@ zones:
- name: internet
settings:
configuration:
network: 192.168.1.0/24
host_start: 192.168.1.10
host_stop: 192.168.1.100
dns: [192.168.1.2]
gateway: 192.168.1.254
network: 192.168.0.0/24
host:
start: 192.168.0.150
stop: 192.168.0.200
dns: [192.168.0.1]
vlan_id: 0
gateway: 192.168.0.1
clusters:
- name: cluster.cadoles.com
- name: hapy.ac-test.fr
zone: internet
zones: [internet]
settings:
configuration:
network:
virtual_ip: 192.168.1.1
virtual_ip: 192.168.1.1
opennebula:
one_user: eoleone
one_password: eole
nodes:
- name: node1.cadoles.com
zones: [internet]
servermodels:
- name: unbound
@ -29,27 +33,12 @@ servermodels:
unbound_allowed_client_cidr: 192.168.1.0/24
reseau:
unbound_route_address: 192.168.1.254
unbound:
unbound_zone_cadoles_com:
hostname_cadoles_com:
hostname_cadoles_com:
- toto
- titi
ip_cadoles_com:
- index: 0
value: 192.168.1.25
type_cadoles_com:
- index: 1
value: CNAME
cname_cadoles_com:
- index: 1
value: toto.cadoles.com
- name: aca
applicationservices: [openssh-server]
settings:
configuration:
serveur_ssh:
ssh_allow_networks: admin.cadoles.com
ssh_server:
ssh_allow_cidr: 192.168.0.0/24
children:
- name: etb1
children:
@ -57,8 +46,21 @@ servermodels:
other_parents: [unbound]
settings:
configuration:
reseau:
unbound_domain_name: dns.cadoles.com
unbound:
unbound_zone_cadoles_com:
hostname_cadoles_com:
hostname_cadoles_com:
- toto
- titi
ip_cadoles_com:
- index: 0
value: 192.168.1.25
type_cadoles_com:
- index: 1
value: CNAME
cname_cadoles_com:
- index: 1
value: toto.cadoles.com
organizations:
- name: cadoles.com
@ -67,16 +69,13 @@ organizations:
zones: [internet]
servers:
- name: dns.cadoles.com
cluster: cluster.cadoles.com
cluster: hapy.ac-test.fr
zones: [internet]
servermodel: unbound_etab1
settings:
configuration:
reseau:
unbound_ip_address_cidr: 192.168.1.2/24
opennebula:
cpu: 0.2
vcpu: 2
memory: 2
memory: 2048
- name: etab2
zones: [internet]

View File

@ -34,31 +34,35 @@ cucchiaiata-cli v1.user.role.create --user_login gnunux \
cucchiaiata-cli v1.infra.zone.create --zone_name internet
# zone configuration
S=$(get_id "cucchiaiata-cli v1.setting.session.zone.start --zone_name internet")
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.network "192.168.1.0/24" \
--configuration.host_start "192.168.1.10" \
--configuration.host_stop "192.168.1.100" \
--configuration.dns 192.168.1.2 \
--configuration.gateway 192.168.1.254
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.network "192.168.0.0/24" \
--configuration.host.start "192.168.0.150" \
--configuration.host.stop "192.168.0.200" \
--configuration.dns 192.168.0.1 \
--configuration.vlan_id 0 \
--configuration.gateway 192.168.0.1
cucchiaiata-cli v1.setting.session.validate --session_id $S
cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
# Create the cluster cluster.cadoles.com
# Create the cluster hapy.ac-test.fr
# +---------------------------+
# | cluster.cadoles.com | +~~~~~~~~~~+
# | hapy.ac-test.fr | +~~~~~~~~~~+
# | +--------------------+ |-------! ZONE !
# | | node1.cadoles.com |---|-------! internet !
# | +--------------------+ | +~~~~~~~~~~+
# +---------------------------+
cucchiaiata-cli v1.infra.cluster.create --cluster_name cluster.cadoles.com \
--zone_name internet
cucchiaiata-cli v1.infra.cluster.create --cluster_name hapy.ac-test.fr \
--zone_name internet \
--zones_name internet
cucchiaiata-cli v1.infra.cluster.node.create --node_name node1.cadoles.com \
--cluster_name cluster.cadoles.com \
--zones_name internet
--cluster_name hapy.ac-test.fr
# configuration
S=$(get_id "cucchiaiata-cli v1.setting.session.cluster.start --cluster_name cluster.cadoles.com")
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.network.virtual_ip "192.168.1.1"
S=$(get_id "cucchiaiata-cli v1.setting.session.cluster.start --cluster_name hapy.ac-test.fr")
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.virtual_ip "192.168.0.115"
# FIXME endpoint == https://<cluster_name>/RPC2
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.opennebula.one_user "eoleone"
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.opennebula.one_password "eole"
cucchiaiata-cli v1.setting.session.validate --session_id $S
cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
@ -92,29 +96,24 @@ cucchiaiata-cli v1.setting.servermodel.create --servermodel_name unbound --appli
cucchiaiata-cli v1.setting.servermodel.create --servermodel_name aca --applicationservices_name openssh-server
cucchiaiata-cli v1.setting.servermodel.create --servermodel_name etab1 --parents_name aca
cucchiaiata-cli v1.setting.servermodel.create --servermodel_name unbound_etab1 --parents_name etab1 unbound
cucchiaiata-cli v1.setting.servermodel.create --servermodel_name nsd_etab1 --parents_name etab1 --applicationservices_name nsd
# configuration
# Servermodel ACA
S=$(get_id "cucchiaiata-cli v1.setting.session.servermodel.start --servermodel_name aca")
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.serveur_ssh.ssh_allow_networks admin.cadoles.com
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.ssh_server.ssh_allow_cidr 192.168.0.0/24
cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
# Servermodel unbound
S=$(get_id "cucchiaiata-cli v1.setting.session.servermodel.start --servermodel_name unbound")
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.serveur_dns.unbound_local_zones cadoles.com \
--configuration.reseau.unbound_route_address 192.168.1.254 \
--configuration.serveur_dns.unbound_allowed_client_cidr 192.168.1.0/24
cucchiaiata-cli v1.setting.session.filter --session_id "$S" --namespace unbound
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --unbound.unbound_zone_cadoles_com.hostname_cadoles_com.hostname_cadoles_com toto titi \
--unbound.unbound_zone_cadoles_com.hostname_cadoles_com.ip_cadoles_com 0 192.168.1.25 \
--unbound.unbound_zone_cadoles_com.hostname_cadoles_com.type_cadoles_com 1 CNAME \
--unbound.unbound_zone_cadoles_com.hostname_cadoles_com.cname_cadoles_com 1 toto.cadoles.com
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.dns_resolver.unbound_allowed_client_cidr 192.168.0.0/24
cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
# Servermodel unbound_etab1
S=$(get_id "cucchiaiata-cli v1.setting.session.servermodel.start --servermodel_name unbound_etab1")
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.reseau.unbound_domain_name dns.cadoles.com
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.dns_resolver.unbound_forward_zones.unbound_forward_zones cadoles.com \
--configuration.dns_resolver.unbound_forward_zones.unbound_forward_addresses 0 192.168.0.151
cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
# Server
@ -128,17 +127,34 @@ cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
# '-> dns.cadoles.com (server)
cucchiaiata-cli v1.infra.server.create --server_name dns.cadoles.com \
--site_name etab1 \
--cluster_name cluster.cadoles.com \
--cluster_name hapy.ac-test.fr \
--zones_name internet \
--servermodel_name unbound_etab1
cucchiaiata-cli v1.infra.server.create --server_name nsd.cadoles.com \
--site_name etab1 \
--cluster_name hapy.ac-test.fr \
--zones_name internet \
--servermodel_name nsd_etab1
# configuration
sleep 1
S=$(get_id "cucchiaiata-cli v1.setting.session.server.start --server nsd.cadoles.com")
#FIXME IP en dure ?
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.dns_server.nsd_allowed_client_cidr 192.168.0.150/32 \
--configuration.dns_zone.nsd_zones cadoles.com
cucchiaiata-cli v1.setting.session.filter --session_id "$S" --namespace nsd
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --nsd.nsd_zone_cadoles_com.hostname_cadoles_com.hostname_cadoles_com toto titi \
--nsd.nsd_zone_cadoles_com.hostname_cadoles_com.ip_cadoles_com 0 192.168.0.25 \
--nsd.nsd_zone_cadoles_com.hostname_cadoles_com.type_cadoles_com 1 CNAME \
--nsd.nsd_zone_cadoles_com.hostname_cadoles_com.cname_cadoles_com 1 toto.cadoles.com
cucchiaiata-cli v1.setting.session.validate --session_id $S
cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
S=$(get_id "cucchiaiata-cli v1.setting.session.server.start --server dns.cadoles.com")
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.reseau.unbound_ip_address_cidr 192.168.1.2/24
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.dns_resolver.unbound_default_forwards 192.168.0.1
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.dns_resolver.unbound_local_authority "nsd.cadoles.com"
cucchiaiata-cli v1.setting.session.filter --session_id "$S" --namespace opennebula
cucchiaiata-cli v1.setting.session.configure --session_id "$S" --opennebula.cpu 0.2 \
--opennebula.vcpu 2 \
--opennebula.memory 2
--opennebula.vcpu 2
cucchiaiata-cli v1.setting.session.validate --session_id $S
cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
@ -147,11 +163,8 @@ cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save
#=======================================================================================================
# Generate configuration
cucchiaiata-cli v1.setting.config.configuration.server.deploy --server_name dns.cadoles.com
cucchiaiata-cli v1.setting.template.generate --server_name dns.cadoles.com
# Generate cluster's configurtion
#cucchiaiata-cli v1.provider.configure -c cluster.cadoles.com
#cucchiaiata-cli v1.provider.deploy --server dns.cadoles.com
cucchiaiata-cli v1.infra.cluster.deploy --cluster_name hapy.ac-test.fr
cucchiaiata-cli v1.infra.zone.deploy --zone_name internet
cucchiaiata-cli v1.infra.server.deploy --server_name nsd.cadoles.com
cucchiaiata-cli v1.infra.server.deploy --server_name dns.cadoles.com
echo "fin"

View File

@ -1,23 +1,42 @@
#!/usr/bin/python3
"""Zephir-cmd-input script
"""
from os import environ
from sys import exit, argv
from json import dumps
from traceback import print_exc
from cucchiaiata import Parser, config, Configuration
from json import dumps
from cucchiaiata import Parser, config, Configuration, JsonError
from cucchiaiata.i18n import _
from cucchiaiata.output.interactive import get as interactive_get
from cucchiaiata.output.json import get as json_get
def main():
dico = {'interactive': interactive_get,
'json': json_get,
}
default_outputs = ','.join(dico.keys())
outputs = [dico[output] for output in environ.get('RISOTTO_OUTPUT', default_outputs).split(',')]
try:
if len(argv) > 2 and argv[1] == 'v1.setting.session.configure':
Configuration().get()
else:
parser = Parser()
print(dumps(parser.get(),
indent=config.indent))
message = parser.remote_config.option('message').value.get()
for output in outputs:
func = output(message)
if func:
func(parser.get(),
config,
)
break
except KeyboardInterrupt:
pass
except JsonError as err:
print(dumps(err.message,
indent=config.indent),
)
exit(1)
except Exception as err:
if config.debug:
print_exc()

View File

@ -5,8 +5,9 @@ from sys import exit, argv
from yaml import load, SafeLoader, YAMLError
from time import sleep
from os.path import isfile
from json import dumps
from cucchiaiata import Configuration
from cucchiaiata import Configuration, JsonError, config
from cucchiaiata.common import Common
from cucchiaiata.i18n import _
@ -33,6 +34,9 @@ class Import(Common):
'zone',
zone,
)
self.send('v1.infra.zone.deploy',
zone_name=zone['name'],
)
def parse_clusters(self) -> None:
for cluster in self.config.get('clusters', []):
@ -40,14 +44,17 @@ class Import(Common):
'cluster',
cluster,
zone_name=cluster['zone'],
zones_name=cluster['zones'],
)
for node in cluster.get('nodes', []):
self.configuration('infra',
'cluster.node',
node,
cluster_name=cluster['name'],
zones_name=node['zones'],
)
self.send('v1.infra.cluster.deploy',
cluster_name=cluster['name'],
)
def parse_servermodels(self) -> None:
for servermodel in self.config.get('servermodels', []):
@ -75,10 +82,7 @@ class Import(Common):
zones_name=server['zones'],
servermodel_name=server['servermodel'],
)
self.send('v1.setting.config.configuration.server.deploy',
server_name=server['name'],
)
self.send('v1.setting.template.generate',
self.send('v1.infra.server.deploy',
server_name=server['name'],
)
@ -96,9 +100,12 @@ class Import(Common):
if 'settings' in dico:
#FIXME
sleep(1)
self.apply_settings(element,
dico,
)
try:
self.apply_settings(element,
dico,
)
except JsonError as err:
raise Exception(f'unable to configure {element} "{dico["name"]}": {err.message["reason"]}')
def apply_settings(self,
element: str,
@ -135,10 +142,10 @@ class Import(Common):
value = [value]
tiramisu.option(key).value.set(value)
except ValueError as err:
print(_(f'error when setting "{domain}" "{dico["name"]}": "{key}" with value "{value}": {err}'))
print(_(f'error when setting "{element}" "{dico["name"]}": "{key}" with value "{value}": {err}'))
exit(1)
except Exception as err:
print(_(f'unexpected error when setting "{domain}" "{dico["name"]}": "{key}" with value "{value}": {err}'))
print(_(f'unexpected error when setting "{element}" "{dico["name"]}": "{key}" with value "{value}": {err}'))
exit(1)
self.send_configuration(tiramisu,
session_id,
@ -212,7 +219,14 @@ if __name__ == "__main__":
print(_(f'usage: {argv[0]} filename.yaml'))
exit(1)
imp = Import(argv[1])
imp.parse_zones()
imp.parse_clusters()
imp.parse_servermodels()
imp.parse_organizations()
try:
imp.parse_zones()
imp.parse_clusters()
imp.parse_servermodels()
imp.parse_organizations()
except JsonError as err:
print(err.message['reason'])
exit(1)
except Exception as err:
print(err)
exit(1)

View File

@ -3,6 +3,6 @@ from setuptools import setup, find_packages
setup(
name='cucchiaiata',
version='0.1',
packages=['cucchiaiata' ],
packages=['cucchiaiata', 'cucchiaiata.output'],
package_dir={"": "src"},
)

View File

@ -1,6 +1,7 @@
from .parser import Parser
from .configuration import Configuration
from .config import config
from .common import JsonError
__all__ = ('Parser', 'config')
__all__ = ('Parser', 'config', 'Configuration', 'JsonError')
__version__ = "0.0.1"

View File

@ -1,11 +1,14 @@
from os import environ
from os.path import isfile
from requests import get, post
from json import dumps
from typing import Dict
from .config import config
from tiramisu_api import Config
from .config import config
from .i18n import _
if config.allow_insecure_https:
import warnings
@ -13,15 +16,14 @@ if config.allow_insecure_https:
warnings.simplefilter('ignore', InsecureRequestWarning)
class JsonError(Exception):
pass
class Common:
def __init__(self):
self.cucchiaiata_config = config
def get_token(self):
if isfile(self.cucchiaiata_config.token_file):
return open(self.cucchiaiata_config.token_file).read()
return ''
def get_error_from_http(self,
req):
try:
@ -36,8 +38,7 @@ class Common:
config_type=Config,
):
"retrieves the remote config from the distant api description"
token = self.get_token()
headers = {'Authorization':'Bearer {}'.format(token)}
headers = get_headers()
req = get(url,
headers=headers,
verify=config.allow_insecure_https,
@ -78,12 +79,22 @@ class Common:
self.send('v1.setting.session.validate',
session_id=session_id,
)
except Exception as err:
except JsonError as err:
self.send('v1.setting.session.stop',
session_id=session_id,
)
print(_(f'error when validate setting to "{name}" "{dico["name"]}": {err}'))
exit(1)
raise err from err
def get_headers():
headers = {}
if isfile(config.token_file):
with open(config.token_file) as token_file:
token = token_file.read()
headers['Authorization'] = f'Bearer {token}'
if 'FORCE_RISOTTO_USER' in environ:
headers['username'] = environ['FORCE_RISOTTO_USER']
return headers
def send_data(uri: str,
@ -96,12 +107,14 @@ def send_data(uri: str,
)
ret = post(final_url,
data=dumps(payload),
headers=get_headers(),
verify=config.allow_insecure_https)
if ret.status_code != 200:
try:
response = ret.json()
except:
raise Exception(ret.text)
response = ret.json()
if 'error' in response:
if 'reason' in response['error']['kwargs']:
raise Exception("{}".format(response['error']['kwargs']['reason']))
raise Exception('erreur inconnue')
if response['type'] == 'error':
err = JsonError()
err.message = response['response']
raise err
return response['response']

View File

View File

@ -0,0 +1,90 @@
from paramiko.config import SSHConfig
from os.path import expandvars, isdir, isfile, join
from os import open as os_open, write, close, truncate, makedirs, O_WRONLY, O_CREAT
def setting_pki_openssh_client(dico, config):
config_dir = expandvars('$HOME/.ssh')
config_file = join(config_dir, 'config')
identityfile = join(expandvars('$HOME/.ssh'), f'risotto_{dico["organization_name"]}')
known_hosts = expandvars('$HOME/.ssh/known_hosts')
hostname = f'*.{dico["organization_name"]}'
new_data = {'identityfile': [identityfile],
'stricthostkeychecking': 'yes',
'hostname': hostname,
'user': dico['cn'],
}
ssh = SSHConfig()
if isfile(config_file):
ssh.parse(open(config_file))
if hostname not in ssh.get_hostnames():
print(f'\n\nIl faudrait ajouter dans le fichier "{config_file}" :')
print(f'Host {hostname}')
for key, value in new_data.items():
if key == 'hostname':
continue
print(f' {key} {value}')
print('\n')
else:
current_data = dict(ssh.lookup(hostname))
if current_data != new_data:
current = set(current_data)
new = set(new_data)
add = new - current
modify = [key for key in new if key in current and current_data[key] != new_data[key]]
if add or modify:
print(f'\n\nModifications suggérées de la section "Host {hostname}" du fichier "{config_file}" :')
for line in add:
value = new_data[line]
if isinstance(value, list):
value = ','.join(value)
print(f' - ajouter "{line} {value}"')
for line in modify:
value = new_data[line]
if isinstance(value, list):
value = ','.join(value)
print(f' - modifier "{line} {current_data[line]}" en "{line} {value}"')
print('\n')
else:
if not isdir(config_dir):
makedirs(config_dir, 0o700)
fh = os_open(config_file, O_WRONLY | O_CREAT, 0o400)
truncate(fh, 0)
write(fh, f'Host {hostname}\n'.encode())
for key, value in new_data.items():
if key == 'hostname':
continue
if isinstance(value, list):
value = ','.join(value)
write(fh, f' {key} {value}\n'.encode())
close(fh)
fh = os_open(f'{identityfile}.pub', O_WRONLY | O_CREAT, 0o400)
truncate(fh, 0)
write(fh, dico['certificate'].encode())
write(fh, b'\n')
close(fh)
if 'private_key' in dico:
fh = os_open(identityfile, O_WRONLY | O_CREAT, 0o400)
truncate(fh, 0)
write(fh, dico['private_key'].encode())
write(fh, b'\n')
close(fh, )
content = [f'@cert-authority *.cadoles.com {dico["chain"]}']
if isfile(known_hosts):
with open(known_hosts) as fh:
old = fh.read().strip()
for line in old.split('\n'):
if line.startswith(f'@cert-authority {hostname} '):
continue
content.append(line)
fh = os_open(known_hosts, O_WRONLY | O_CREAT, 0o400)
truncate(fh, 0)
for line in content:
write(fh, f'{line}\n'.encode())
close(fh)
print('Certificat mise à jour')
def get(message):
if message == 'v1.setting.pki.openssh.client.get':
return setting_pki_openssh_client

View File

@ -0,0 +1,10 @@
from json import dumps
def print_json(dico, config):
indent = config.indent
print(dumps(dico, indent = indent))
def get(message):
return print_json