You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
5.7 KiB

import copy
import os
import re
import sh
import shutil
import textwrap
import yaml
class Hosts(object):
def __init__(self, config_dir):
self.d = f'{config_dir}/inventory'
self.f = f'{self.d}/hosts.yml'
def load(self):
if os.path.exists(self.f):
self.hosts = yaml.load(open(self.f).read())['all']['hosts']
self.hosts = {}
return self
def get_ip(self, host):
return self.hosts.get(host, {}).get('ansible_host')
def get_port(self, host):
return self.hosts.get(host, {}).get('ansible_port', '22')
def save(self):
if not os.path.exists(self.d):
content = yaml.dump(
'all': {
'hosts': self.hosts,
open(self.f, 'w').write(content)
def missings(self, names):
return [name for name in names if name not in self.hosts]
def create_or_update(self, name, ipv4, port):
if self.get_ip(name) != ipv4:
self.hosts[name] = {'ansible_host': ipv4, 'ansible_port': port}
return True
return False
def delete(self, name):
if name in self.hosts:
del self.hosts[name]
class DotEnough(object):
def __init__(self, config_dir, domain):
self.domain = domain
self.config_dir = config_dir
d = f'{self.config_dir}/inventory/group_vars/all'
if not os.path.exists(d):
def ensure(self):
def ensure_ssh_key(self):
path = f'{self.config_dir}/infrastructure_key'
if not os.path.exists(path):
sh.ssh_keygen('-f', path, '-N', '', '-b', '4096', '-t', 'rsa')
return path
def public_key(self):
return f'{self.ensure_ssh_key()}.pub'
def private_key(self):
return self.ensure_ssh_key()
def populate_config(self, certificate_authority):
d = f'{self.config_dir}/inventory/group_vars/all'
if not os.path.exists(d):
if not os.path.exists(f'{d}/private-key.yml'):
open(f'{d}/private-key.yml', 'w').write(textwrap.dedent(f"""\
ssh_private_keyfile: {self.config_dir}/infrastructure_key
if not os.path.exists(f'{d}/domain.yml'):
open(f'{d}/domain.yml', 'w').write(textwrap.dedent(f"""\
domain: {self.domain}
production_domain: {self.domain}
if not os.path.exists(f'{d}/certificate.yml'):
def service2group(service):
return f'{service}-service-group'
def service_add_to_group(self, service, host):
s = f'{self.config_dir}/inventory/services.yml'
if os.path.exists(s):
services = yaml.load(open(s).read())
services = {}
group = self.service2group(service)
if group not in services:
services[group] = {'hosts': {}}
if host not in services[group]['hosts']:
services[group]['hosts'][host] = None
open(s, 'w').write(yaml.dump(services, indent=4))
return services
def set_certificate(self, certificate_authority):
d = f'{self.config_dir}/inventory/group_vars/all'
open(f'{d}/certificate.yml', 'w').write(textwrap.dedent(f"""\
certificate_authority: {certificate_authority}
class DotEnoughOpenStack(DotEnough):
def __init__(self, config_dir, domain):
super().__init__(config_dir, domain)
self.clouds_file = f'{self.config_dir}/inventory/group_vars/all/clouds.yml'
def set_clouds_file(self, clouds_file):
shutil.copy(clouds_file, self.clouds_file)
def ensure(self):
self.set_missing_config_file_from_openrc(f'{self.config_dir}/', self.clouds_file)
def set_missing_config_file_from_openrc(openrc, config_file):
if os.path.exists(openrc) and not os.path.exists(config_file):
DotEnoughOpenStack.openrc2clouds(openrc, config_file)
return True
return False
def openrc2clouds(openrc, clouds):
c = {
'auth': {
'user_domain_name': 'Default',
'password': 'PLACEHOLDER',
for line in open(openrc).readlines():
r ='export\s+(OS_\w+)="(.*)"', line)
if not r:
r ='export\s+(OS_\w+)=(.*)\s*', line)
if not r:
(k, v) =, 2)
if k == 'OS_REGION_NAME':
c['region_name'] = v
elif k == 'OS_AUTH_URL':
c['auth']['auth_url'] = v
elif k == 'OS_PROJECT_NAME' or k == 'OS_TENANT_NAME':
c['auth']['project_name'] = v
elif k == 'OS_PROJECT_ID' or k == 'OS_TENANT_ID':
c['auth']['project_id'] = v
elif k == 'OS_USERNAME':
c['auth']['username'] = v
elif k == 'OS_PASSWORD' and v != '$OS_PASSWORD_INPUT':
c['auth']['password'] = v
clone = copy.deepcopy(c)
clone['region_name'] = 'DE1'
open(clouds, 'w').write(yaml.dump({
'clouds': {
'production': c,
'clone': clone,
return c
class DotEnoughDocker(DotEnough):
def ensure(self):