#!/usr/bin/python3 import os import argparse import subprocess import yaml parser = argparse.ArgumentParser() parser.add_argument('--config', type=str, default='/etc/publik/publik.conf') parser.add_argument('--simulate', action='store_true') parser.add_argument('--configure', action='store_true') args = parser.parse_args() model = """DATABASES['default']['HOST'] = '{host}' DATABASES['default']['PORT'] = {port} DATABASES['default']['PASSWORD'] = '{password}'""" def run_pg(connection, cmd): cmd = cmd.replace('"', '\\"') if connection.get('host') == 'localhost' and not connection.get('admin'): subprocess.call('echo "%s" | sudo -u postgres psql' % cmd, shell=True) else: admin = connection.get('admin') subprocess.call("echo '%s' | psql -h -U %s -W" % (cmd, admin), shell=True) def main(): if not os.path.isfile(args.config): raise(Exception('Configuration file not found: %s' % args.config)) with open(args.config) as fh: cfg = yaml.load(fh) if 'defaults' in cfg.keys(): defaults = cfg.get('defaults') else: defaults = {} if 'databases' not in defaults.keys() and 'instances' not in cfg.keys(): raise(Exception('No "instances" nor "defaults" keys found in configuration file')) for instance, data in cfg['instances'].items(): if 'databases' not in data.keys(): data['databases'] = defaults['databases'] if 'connection' in defaults.keys(): connection = defaults['connection'] if 'connection' in data.keys(): connection.update(data['connection']) else: connection = data['connection'] if args.configure: if 'roles' not in data.keys(): raise(Exception('Not implemented: no passwords defined')) configure_briques(connection, data['databases'], data['roles']) else: if 'roles' not in data.keys(): print('No "roles" key found, going for passwordless configuration') data['roles'] = False create_databases(connection, instance, data['databases'], data['roles']) def configure_briques(connection, databases, roles): for database, role in databases.items(): if database == 'wcs': continue password = roles[role] if database == 'authentic2_multitenant': service = 'authentic2-multitenant' user = 'authentic-multitenant' else: user, service = database, database settings_d = '/etc/%s/settings.d' % service settings = '%s/connection.py' % settings_d if not os.path.isdir(settings_d) and not args.simultate: os.system('mkdir -p %s' % settings_d) s = model.format(database=database, host=connection['host'], port=connection['port'], password=password) if args.simulate: print(s) continue with open(settings, 'w') as fh: fh.write(s) os.system('chown -R %s %s' % (user, settings_d)) def create_databases(connection, instance, databases, roles): count = len(databases.keys()) print('instance {} has {} components'.format(instance, count)) cmds = [] for database, role in databases.items(): if roles: password = roles[role] else: password = False cmds.append(gen_cmd(database, role, password)) if args.simulate: print(connection) for c in cmds: print(c) else: run_pg(connection, " ".join(cmds)) def gen_cmd(database, role, password): out = [] if password: out.append("CREATE USER \"{}\" PASSWORD '{}';".format(role, password)) else: out.append("CREATE USER \"{}\";".format(role)) out.append("CREATE DATABASE {} WITH OWNER = \"{}\" TEMPLATE = template0 " "LC_COLLATE = 'fr_FR.UTF-8' LC_CTYPE = 'fr_FR.UTF-8';".format(database, role)) if database == 'wcs': out.append("ALTER USER wcs CREATEDB;") return " ".join(out) if __name__ == '__main__': main()