comparison twisted/plugins/pubsub.py @ 428:34bd55179e22

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.
author Goffi <goffi@goffi.org>
date Fri, 09 Oct 2020 18:26:50 +0200
parents 6f8e1c180c83
children 5a0ada3b61ca
comparison
equal deleted inserted replaced
427:f6f4f99f1a1b 428:34bd55179e22
50 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 50 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51 51
52 52
53 import sys 53 import sys
54 import csv 54 import csv
55 import os
55 from os.path import expanduser, realpath 56 from os.path import expanduser, realpath
56 import configparser 57 import configparser
57 # patch for Python 3.8 compatibility 58 # patch for Python 3.8 compatibility
58 from sat_tmp.twisted import install as install_twisted_patches 59 from sat_tmp.twisted import install as install_twisted_patches
59 install_twisted_patches() 60 install_twisted_patches()
92 ['db_name', None, 'pubsub', 'Database name (pgsql backend)'], 93 ['db_name', None, 'pubsub', 'Database name (pgsql backend)'],
93 ['db_pass', None, None, 'Database password (pgsql backend)'], 94 ['db_pass', None, None, 'Database password (pgsql backend)'],
94 ['db_host', None, None, 'Database host (pgsql backend)'], 95 ['db_host', None, None, 'Database host (pgsql backend)'],
95 ['db_port', None, None, 'Database port (pgsql backend)'], 96 ['db_port', None, None, 'Database port (pgsql backend)'],
96 ] 97 ]
97 # here for future use 98
98 OPT_PARAMETERS_CFG = [ 99 OPT_PARAMETERS_CFG = [
99 ["admins_jids_list", None, [], "List of administrators' bare jids", 100 ["admins_jids_list", None, [], "List of administrators' bare jids",
100 coerceJidListType] 101 coerceJidListType]
101 ] 102 ]
103
104 # prefix used for environment variables
105 ENV_PREFIX = "SAT_PUBSUB_"
106 # mapping from option name to environment variables to use
107 # each parameter name links to a list of variable environment name
108 # if an environment variable of one of the names exists it will be used
109 # as default value, with priority over config file
110 ENV_OPT_MAP = {
111 # we use the same environment variables as PostgreSQL
112 'db_user': ['PGUSER'],
113 'db_name': ['PGDATABASE'],
114 'db_pass': ['PGPASSWORD'],
115 'db_host': ['PGHOST'],
116 'db_port': ['PGPORT'],
117 }
118 for opt in OPT_PARAMETERS_BOTH + OPT_PARAMETERS_CFG:
119 name = opt[0]
120 env_name = f"{ENV_PREFIX}{name.upper()}"
121 ENV_OPT_MAP.setdefault(name, []).append(env_name)
102 122
103 CONFIG_FILENAME = 'sat' 123 CONFIG_FILENAME = 'sat'
104 # List of the configuration filenames sorted by ascending priority 124 # List of the configuration filenames sorted by ascending priority
105 CONFIG_FILES = [realpath(expanduser(path) + CONFIG_FILENAME + '.conf') for path in ( 125 CONFIG_FILES = [realpath(expanduser(path) + CONFIG_FILENAME + '.conf') for path in (
106 '/etc/', '/etc/{}/'.format(CONFIG_FILENAME), 126 '/etc/', '/etc/{}/'.format(CONFIG_FILENAME),
133 # FIXME: must be refactored + code can be factorised with backend 153 # FIXME: must be refactored + code can be factorised with backend
134 config_parser = configparser.ConfigParser() 154 config_parser = configparser.ConfigParser()
135 config_parser.read(CONFIG_FILES) 155 config_parser.read(CONFIG_FILES)
136 for param in self.optParameters + OPT_PARAMETERS_CFG: 156 for param in self.optParameters + OPT_PARAMETERS_CFG:
137 name = param[0] 157 name = param[0]
138 try: 158 for env_name in ENV_OPT_MAP[name]:
139 value = config_parser.get(CONFIG_SECTION, name) 159 # we first check if value is set as an environment variable
160 value = os.getenv(env_name)
161 if value is not None:
162 self.setDefaultOption(param, value)
163 break
164 else:
165 # no environment variable set, let's try with configuration
140 try: 166 try:
141 param[2] = param[4](value) 167 value = config_parser.get(CONFIG_SECTION, name)
142 except IndexError: # the coerce method is optional 168 self.setDefaultOption(param, value)
143 param[2] = value 169 except (configparser.NoSectionError, configparser.NoOptionError):
144 except Exception as e: 170 pass
145 log.err('Invalid value for setting "{name}": {msg}'.format(
146 name=name, msg=e))
147 sys.exit(1)
148 except (configparser.NoSectionError, configparser.NoOptionError):
149 pass
150 usage.Options.__init__(self) 171 usage.Options.__init__(self)
151 for opt_data in OPT_PARAMETERS_CFG: 172 for opt_data in OPT_PARAMETERS_CFG:
152 self[opt_data[0]] = opt_data[2] 173 self[opt_data[0]] = opt_data[2]
174
175 def setDefaultOption(self, param, value):
176 """Set default option value using coerce method when needed
177
178 If the value is invalid, we quit the program with exit code 1
179 """
180 try:
181 param[2] = param[4](value)
182 except IndexError: # the coerce method is optional
183 param[2] = value
184 except Exception as e:
185 log.err('Invalid value for setting "{name}": {msg}'.format(
186 name=name, msg=e))
187 sys.exit(1)
153 188
154 def postOptions(self): 189 def postOptions(self):
155 if self['backend'] not in ['pgsql', 'memory']: 190 if self['backend'] not in ['pgsql', 'memory']:
156 raise usage.UsageError("Unknown backend!") 191 raise usage.UsageError("Unknown backend!")
157 if self['backend'] == 'memory': 192 if self['backend'] == 'memory':