# HG changeset patch # User Goffi # Date 1602260810 -7200 # Node ID 34bd55179e22f4d4b248bbfb3241da6f287354cf # Parent f6f4f99f1a1b6a0f20891f4bf056ec9bc9868071 environment variables can now be used to set options: if an environment variable is set using `SAT_PUBSUB_[OPTION NAME]` it will be used if not specified directly in command line. Options are retrieved in this order of priority: - command line (highest priority) - environment variable - option set in `sat.conf` For database options, following PostgreSQL aliases can also be used: PGUSER, PGDATABASE, PGPASSWORD, PGHOST, PGPORT. diff -r f6f4f99f1a1b -r 34bd55179e22 twisted/plugins/pubsub.py --- a/twisted/plugins/pubsub.py Fri Oct 09 18:22:45 2020 +0200 +++ b/twisted/plugins/pubsub.py Fri Oct 09 18:26:50 2020 +0200 @@ -52,6 +52,7 @@ import sys import csv +import os from os.path import expanduser, realpath import configparser # patch for Python 3.8 compatibility @@ -94,12 +95,31 @@ ['db_host', None, None, 'Database host (pgsql backend)'], ['db_port', None, None, 'Database port (pgsql backend)'], ] -# here for future use + OPT_PARAMETERS_CFG = [ ["admins_jids_list", None, [], "List of administrators' bare jids", coerceJidListType] ] +# prefix used for environment variables +ENV_PREFIX = "SAT_PUBSUB_" +# mapping from option name to environment variables to use +# each parameter name links to a list of variable environment name +# if an environment variable of one of the names exists it will be used +# as default value, with priority over config file +ENV_OPT_MAP = { + # we use the same environment variables as PostgreSQL + 'db_user': ['PGUSER'], + 'db_name': ['PGDATABASE'], + 'db_pass': ['PGPASSWORD'], + 'db_host': ['PGHOST'], + 'db_port': ['PGPORT'], +} +for opt in OPT_PARAMETERS_BOTH + OPT_PARAMETERS_CFG: + name = opt[0] + env_name = f"{ENV_PREFIX}{name.upper()}" + ENV_OPT_MAP.setdefault(name, []).append(env_name) + CONFIG_FILENAME = 'sat' # List of the configuration filenames sorted by ascending priority CONFIG_FILES = [realpath(expanduser(path) + CONFIG_FILENAME + '.conf') for path in ( @@ -135,22 +155,37 @@ config_parser.read(CONFIG_FILES) for param in self.optParameters + OPT_PARAMETERS_CFG: name = param[0] - try: - value = config_parser.get(CONFIG_SECTION, name) + for env_name in ENV_OPT_MAP[name]: + # we first check if value is set as an environment variable + value = os.getenv(env_name) + if value is not None: + self.setDefaultOption(param, value) + break + else: + # no environment variable set, let's try with configuration try: - param[2] = param[4](value) - except IndexError: # the coerce method is optional - param[2] = value - except Exception as e: - log.err('Invalid value for setting "{name}": {msg}'.format( - name=name, msg=e)) - sys.exit(1) - except (configparser.NoSectionError, configparser.NoOptionError): - pass + value = config_parser.get(CONFIG_SECTION, name) + self.setDefaultOption(param, value) + except (configparser.NoSectionError, configparser.NoOptionError): + pass usage.Options.__init__(self) for opt_data in OPT_PARAMETERS_CFG: self[opt_data[0]] = opt_data[2] + def setDefaultOption(self, param, value): + """Set default option value using coerce method when needed + + If the value is invalid, we quit the program with exit code 1 + """ + try: + param[2] = param[4](value) + except IndexError: # the coerce method is optional + param[2] = value + except Exception as e: + log.err('Invalid value for setting "{name}": {msg}'.format( + name=name, msg=e)) + sys.exit(1) + def postOptions(self): if self['backend'] not in ['pgsql', 'memory']: raise usage.UsageError("Unknown backend!")