6
0
mirror of https://github.com/ChristianLight/tutor.git synced 2024-09-23 01:49:01 +00:00
tutor/configurator/bin/configure.py

173 lines
5.4 KiB
Python
Raw Normal View History

#! /usr/bin/env python3
# coding: utf8
import argparse
import codecs
import json
import os
import random
import string
import sys
from collections import OrderedDict
class Configurator:
def __init__(self, **default_overrides):
self.__values = OrderedDict()
self.__default_values = default_overrides
try:
self.__input = raw_input
except NameError:
self.__input = input
def as_dict(self):
all_values = self.__values.copy()
for key, value in self.__default_values.items():
all_values.setdefault(key, value)
return all_values
def mute(self):
self.__input = None
def add(self, name, question="", default=""):
default = self.__default_values.get(name, default)
value = default
if question:
message = question + " (default: \"{}\"): ".format(default)
value = self.ask(message, default)
self.set(name, value)
return self
def add_boolean(self, name, question, default=True):
default = self.__default_values.get(name, default)
message = question + " ({}) ".format("Y/n" if default else "y/N")
value = None
while value is None:
answer = self.ask(message, default)
value = {
"y": True,
"n": False,
default: default,
}.get(answer)
self.set(name, value)
return self
def ask(self, message, default):
if self.__input:
return self.__input(message) or default
return default
def get(self, name):
return self.__values.get(name)
def set(self, name, value):
self.__values[name] = value
def main():
parser = argparse.ArgumentParser("Config file generator for Open edX")
parser.add_argument('-c', '--config', default=os.path.join("/", "openedx", "config", "config.json"),
help="Load default values from this file. Config values will be saved there.")
subparsers = parser.add_subparsers()
parser_interactive = subparsers.add_parser('interactive')
parser_interactive.add_argument('-s', '--silent', action='store_true',
help=(
"Be silent and accept all default values. "
"This is good for debugging and automation, but "
"probably not what you want"
))
parser_interactive.set_defaults(func=interactive)
parser_substitute = subparsers.add_parser('substitute')
parser_substitute.add_argument('--delimiter', default='$', help="Template file delimiter")
parser_substitute.add_argument('src', help="Template source file")
parser_substitute.add_argument('dst', help="Destination configuration file")
parser_substitute.set_defaults(func=substitute)
args = parser.parse_args()
# Load defaults
defaults = {}
if os.path.exists(args.config):
with open(args.config) as f:
defaults = json.load(f)
configurator = Configurator(**defaults)
args.func(configurator, args)
def interactive(configurator, args):
if args.silent:
configurator.mute()
configurator.add(
'LMS_HOST', "Your website domain name for students (LMS).", 'www.myopenedx.com'
).add(
'CMS_HOST', "Your website domain name for teachers (CMS).", 'studio.myopenedx.com'
).add(
'PLATFORM_NAME', "Platform name/title", "My Open edX"
).add(
'SECRET_KEY', "", random_string(24)
).add(
'MYSQL_DATABASE', "", 'openedx'
).add(
'MYSQL_USERNAME', "", 'openedx'
).add(
'MYSQL_PASSWORD', "", random_string(8),
).add(
'MONGODB_DATABASE', "", 'openedx'
).add(
'XQUEUE_AUTH_USERNAME', "", 'lms'
).add(
'XQUEUE_AUTH_PASSWORD', "", random_string(8),
).add(
'XQUEUE_MYSQL_DATABASE', "", 'xqueue',
).add(
'XQUEUE_MYSQL_USERNAME', "", 'xqueue',
).add(
'XQUEUE_MYSQL_PASSWORD', "", random_string(8),
).add(
'XQUEUE_SECRET_KEY', "", random_string(24),
)
# Save values
with open(args.config, 'w') as f:
json.dump(configurator.as_dict(), f, sort_keys=True, indent=4)
print("\nConfiguration values were saved to ", args.config)
def substitute(configurator, args):
with codecs.open(args.src, encoding='utf-8') as fi:
template = template_class(args.delimiter)(fi.read())
try:
substituted = template.substitute(**configurator.as_dict())
except KeyError as e:
sys.stderr.write("ERROR Missing config value '{}' for template {}\n".format(e.args[0], args.src))
sys.exit(1)
with codecs.open(args.dst, encoding='utf-8', mode='w') as fo:
fo.write(substituted)
print("Generated file {} from template {}".format(args.dst, args.src))
def template_class(user_delimiter='$'):
"""
The default delimiter of the python Template class is '$'. Here, we
generate a Template class with a custom delimiter. This cannot be done
after the class creation because the Template metaclass uses the delimiter
value.
"""
class Template(string.Template):
delimiter = user_delimiter
return Template
def random_string(length):
return "".join([random.choice(string.ascii_letters + string.digits) for _ in range(length)])
if __name__ == '__main__':
main()