2018-08-05 14:26:19 +00:00
|
|
|
#! /usr/bin/env python3
|
|
|
|
# coding: utf8
|
|
|
|
import argparse
|
|
|
|
import codecs
|
|
|
|
import json
|
|
|
|
import os
|
|
|
|
import random
|
|
|
|
import string
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from collections import OrderedDict
|
|
|
|
|
2018-08-05 14:40:51 +00:00
|
|
|
import jinja2
|
|
|
|
|
2018-08-05 14:26:19 +00:00
|
|
|
|
|
|
|
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):
|
2018-08-16 13:59:31 +00:00
|
|
|
return self.__values
|
2018-08-05 14:26:19 +00:00
|
|
|
|
|
|
|
def mute(self):
|
|
|
|
self.__input = None
|
|
|
|
|
|
|
|
def add(self, name, question="", default=""):
|
|
|
|
default = self.__default_values.get(name, default)
|
|
|
|
value = default
|
2018-08-16 13:59:31 +00:00
|
|
|
message = question + " (default: \"{}\"): ".format(default) if question else None
|
|
|
|
value = self.ask(message, default)
|
2018-08-05 14:26:19 +00:00
|
|
|
self.set(name, value)
|
|
|
|
|
|
|
|
return self
|
|
|
|
|
|
|
|
def ask(self, message, default):
|
2018-08-16 13:59:31 +00:00
|
|
|
if self.__input and message:
|
2018-08-05 14:26:19 +00:00
|
|
|
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
|
2018-08-16 13:59:31 +00:00
|
|
|
return self
|
2018-08-05 14:26:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
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"
|
|
|
|
))
|
2018-08-16 13:59:31 +00:00
|
|
|
parser_interactive.add_argument('--activate-https', action='store_true', default=False, help='Activate https feature flag')
|
2018-08-19 12:40:38 +00:00
|
|
|
parser_interactive.add_argument('--activate-xqueue', action='store_true', default=False, help='Activate xqueue feature flag')
|
2018-08-05 14:26:19 +00:00
|
|
|
parser_interactive.set_defaults(func=interactive)
|
|
|
|
|
|
|
|
parser_substitute = subparsers.add_parser('substitute')
|
|
|
|
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()
|
2018-08-16 13:59:31 +00:00
|
|
|
args.func(args)
|
2018-08-05 14:26:19 +00:00
|
|
|
|
2018-08-16 13:59:31 +00:00
|
|
|
def load_config(args):
|
2018-08-05 14:26:19 +00:00
|
|
|
if os.path.exists(args.config):
|
|
|
|
with open(args.config) as f:
|
2018-08-16 13:59:31 +00:00
|
|
|
return json.load(f)
|
|
|
|
return {}
|
2018-08-05 14:26:19 +00:00
|
|
|
|
2018-08-16 13:59:31 +00:00
|
|
|
def interactive(args):
|
|
|
|
print("\n====================================")
|
|
|
|
print(" Interactive configuration ")
|
|
|
|
print("====================================")
|
2018-08-05 14:26:19 +00:00
|
|
|
|
2018-08-16 13:59:31 +00:00
|
|
|
configurator = Configurator(**load_config(args))
|
2018-09-15 09:55:42 +00:00
|
|
|
if args.silent or os.environ.get('SILENT'):
|
2018-08-05 14:26:19 +00:00
|
|
|
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"
|
2018-09-05 10:24:07 +00:00
|
|
|
).add(
|
|
|
|
'CONTACT_EMAIL', "Public contact email address", 'contact@' + configurator.get('LMS_HOST')
|
2018-08-05 14:26:19 +00:00
|
|
|
).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),
|
2018-08-16 13:59:31 +00:00
|
|
|
).set(
|
|
|
|
'ACTIVATE_HTTPS', bool(args.activate_https or os.environ.get('ACTIVATE_HTTPS'))
|
2018-08-19 12:40:38 +00:00
|
|
|
).set(
|
|
|
|
'ACTIVATE_XQUEUE', bool(args.activate_xqueue or os.environ.get('ACTIVATE_XQUEUE'))
|
2018-08-05 14:26:19 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
|
|
|
|
2018-08-16 13:59:31 +00:00
|
|
|
def substitute(args):
|
|
|
|
config = load_config(args)
|
2018-08-05 14:26:19 +00:00
|
|
|
with codecs.open(args.src, encoding='utf-8') as fi:
|
2018-08-05 14:40:51 +00:00
|
|
|
template = jinja2.Template(fi.read(), undefined=jinja2.StrictUndefined)
|
2018-08-05 14:26:19 +00:00
|
|
|
try:
|
2018-08-16 13:59:31 +00:00
|
|
|
substituted = template.render(**config)
|
2018-08-05 14:40:51 +00:00
|
|
|
except jinja2.exceptions.UndefinedError as e:
|
2018-08-05 14:26:19 +00:00
|
|
|
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)
|
|
|
|
|
2018-08-16 13:59:31 +00:00
|
|
|
# Set same permissions as original file
|
|
|
|
os.chmod(args.dst, os.stat(args.src).st_mode)
|
|
|
|
|
2018-08-05 14:26:19 +00:00
|
|
|
print("Generated file {} from template {}".format(args.dst, args.src))
|
|
|
|
|
|
|
|
|
|
|
|
def random_string(length):
|
|
|
|
return "".join([random.choice(string.ascii_letters + string.digits) for _ in range(length)])
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|