publik-common/publik-create-databases

131 lines
4.1 KiB
Python
Executable File

#!/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()