Skip to content

Commit 50eb75e

Browse files
committed
Look for configuration and directories relative to venv
Running CMS outside a venv is no longer supported. When CMS_CONFIG or CMS_RANKING_CONFIG is given, the default configuration is no longer used as fall-back. Errors when reading configuration, including a missing configuration file, are fatal.
1 parent 3bd9d5c commit 50eb75e

File tree

2 files changed

+34
-41
lines changed

2 files changed

+34
-41
lines changed

cms/conf.py

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -174,48 +174,38 @@ def __init__(self):
174174
self.telegram_bot_token = None
175175
self.telegram_bot_chat_id = None
176176

177-
self.log_dir = os.path.join("/", "var", "local", "log", "cms")
178-
self.cache_dir = os.path.join("/", "var", "local", "cache", "cms")
179-
self.data_dir = os.path.join("/", "var", "local", "lib", "cms")
180-
self.run_dir = os.path.join("/", "var", "local", "run", "cms")
181-
paths = [
182-
os.path.join("/", "usr", "local", "etc", "cms.toml"),
183-
os.path.join("/", "etc", "cms.toml"),
184-
]
185-
186-
# Allow user to override config file path using environment
177+
# Try to find CMS installation root from the venv in which we run
178+
self.base_dir = sys.prefix
179+
if self.base_dir == '/usr':
180+
logger.critical('CMS must be run within a Python virtual environment')
181+
sys.exit(1)
182+
self.log_dir = os.path.join(self.base_dir, 'log')
183+
self.cache_dir = os.path.join(self.base_dir, 'cache')
184+
self.data_dir = os.path.join(self.base_dir, 'lib')
185+
self.run_dir = os.path.join(self.base_dir, 'run')
186+
187+
# Default config file path can be overridden using environment
187188
# variable 'CMS_CONFIG'.
188-
CMS_CONFIG_ENV_VAR = "CMS_CONFIG"
189-
if CMS_CONFIG_ENV_VAR in os.environ:
190-
paths = [os.environ[CMS_CONFIG_ENV_VAR]] + paths
189+
default_config_file = os.path.join(self.base_dir, 'etc/cms.toml')
190+
config_file = os.environ.get('CMS_CONFIG', default_config_file)
191191

192-
# Attempt to load a config file.
193-
self._load(paths)
192+
if not self._load_config(config_file):
193+
logging.critical(f'Cannot load configuration file {config_file}')
194+
sys.exit(1)
194195

195196
# If the configuration says to print detailed log on stdout,
196197
# change the log configuration.
197198
set_detailed_logs(self.stream_log_detailed)
198199

199-
def _load(self, paths: list[str]):
200-
"""Try to load the config files one at a time, until one loads
201-
correctly.
202-
203-
"""
204-
for conf_file in paths:
205-
if self._load_unique(conf_file):
206-
break
207-
else:
208-
logging.warning("No configuration file found: "
209-
"falling back to default values.")
210-
211-
def _load_unique(self, path: str):
200+
def _load_config(self, path: str) -> bool:
212201
"""Populate the Config class with everything that sits inside
213202
the TOML file path (usually something like /etc/cms.toml). The
214203
only pieces of data treated differently are the elements of
215204
core_services and other_services that are sent to async
216205
config.
217206
218207
path: the path of the TOML config file.
208+
returns: whether parsing was successful.
219209
220210
"""
221211
# Load config file.
@@ -235,8 +225,6 @@ def _load_unique(self, path: str):
235225
logger.warning("Invalid syntax in file %s: %s", path, error)
236226
return False
237227

238-
logger.info("Using configuration file %s.", path)
239-
240228
if "is_proxy_used" in data:
241229
logger.warning("The 'is_proxy_used' setting is deprecated, please "
242230
"use 'num_proxies_used' instead.")
@@ -263,9 +251,10 @@ def _load_unique(self, path: str):
263251

264252
# Put everything else in self.
265253
for key, value in data.items():
266-
if not hasattr(self, key):
254+
if hasattr(self, key):
255+
setattr(self, key, value)
256+
else:
267257
logger.warning("Unrecognized key %s in config!", key)
268-
setattr(self, key, value)
269258

270259
return True
271260

cmsranking/Config.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,20 @@ def __init__(self):
6060
self.buffer_size = 100 # Needs to be strictly positive.
6161

6262
self.web_dir = pkg_resources.resource_filename("cmsranking", "static")
63-
self.log_dir = os.path.join("/", "var", "local", "log", "cms", "ranking")
64-
self.lib_dir = os.path.join("/", "var", "local", "lib", "cms", "ranking")
65-
self.conf_paths = [
66-
os.path.join("/", "usr", "local", "etc", "cms_ranking.toml"),
67-
os.path.join("/", "etc", "cms_ranking.toml"),
68-
]
63+
64+
# Try to find CMS installation root from the venv in which we run
65+
self.base_dir = sys.prefix
66+
if self.base_dir == '/usr':
67+
logger.critical('CMS must be run within a Python virtual environment')
68+
sys.exit(1)
69+
self.log_dir = os.path.join(self.base_dir, 'log/ranking')
70+
self.lib_dir = os.path.join(self.base_dir, 'lib/ranking')
71+
self.conf_paths = [os.path.join(self.base_dir, 'etc/cms_ranking.toml')]
6972

7073
# Allow users to override config file path using environment
7174
# variable 'CMS_RANKING_CONFIG'.
7275
if CMS_RANKING_CONFIG_ENV_VAR in os.environ:
73-
self.conf_paths = [os.environ[CMS_RANKING_CONFIG_ENV_VAR]] \
74-
+ self.conf_paths
76+
self.conf_paths = [os.environ[CMS_RANKING_CONFIG_ENV_VAR]]
7577

7678
def get(self, key):
7779
"""Get the config value for the given key.
@@ -132,7 +134,9 @@ def _load_many(self, conf_paths: list[str]) -> bool:
132134
conf_path, errno.errorcode[error.errno],
133135
os.strerror(error.errno))
134136
return False
135-
logger.warning("No config file found, using hardcoded defaults.")
137+
tried = " ".join(conf_paths)
138+
logging.warning(f"No configuration file found, tried: {tried}. "
139+
"Falling back to default values.")
136140
return True
137141

138142
def _load_one(self, conf_fobj: typing.BinaryIO) -> bool:

0 commit comments

Comments
 (0)