Skip to content

Commit faea9cd

Browse files
alanbchristieAlan Christie
and
Alan Christie
authored
Initial support for DEPLOYMENT_MODE (#503)
* fix: Adds DEPLOYMENT_MODE env support * feat: Support for DEPLOYMENT_MODE --------- Co-authored-by: Alan Christie <alan.christie@matildapeak.com>
1 parent 5103612 commit faea9cd

File tree

4 files changed

+73
-7
lines changed

4 files changed

+73
-7
lines changed

api/utils.py

+4
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,7 @@ def pretty_request(request, *, tag='', print_body=False):
399399
f'{body}\n'
400400
'- REQUEST END'
401401
)
402+
403+
404+
def deployment_mode_is_production():
405+
return settings.DEPLOYMENT_MODE == "PRODUCTION"

docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ services:
8686
- .:/code/
8787
environment:
8888
AUTHENTICATE_UPLOAD: ${AUTHENTICATE_UPLOAD:-True}
89+
DEPLOYMENT_MODE: 'development'
8990
POSTGRESQL_USER: postgres
9091
# Celery tasks need to run synchronously
9192
CELERY_TASK_ALWAYS_EAGER: 'True'

fragalysis/settings.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,12 @@
237237
OIDC_RENEW_ID_TOKEN_EXPIRY_SECONDS = int(TOKEN_EXPIRY_MINUTES) * 60
238238
# Keycloak mozilla_django_oidc - Settings - End
239239

240+
# The deployment mode.
241+
# Controls the behaviour of the application (it's strictness to errors etc).
242+
# Typically one of "DEVELOPMENT" or "PRODUCTION".
243+
# see api.utils for the 'deployment_mode_is_production()' function.
244+
DEPLOYMENT_MODE = os.environ.get("DEPLOYMENT_MODE", "production").upper()
245+
240246
ROOT_URLCONF = "fragalysis.urls"
241247

242248
STATIC_ROOT = os.path.join(PROJECT_ROOT, "static")
@@ -451,9 +457,9 @@
451457
'api.security': {'level': 'INFO'},
452458
'asyncio': {'level': 'WARNING'},
453459
'celery': {'level': 'INFO'},
454-
'django': {'level': 'INFO'},
455-
'mozilla_django_oidc': {'level': 'INFO'},
456-
'urllib3': {'level': 'INFO'},
460+
'django': {'level': 'WARNING'},
461+
'mozilla_django_oidc': {'level': 'WARNING'},
462+
'urllib3': {'level': 'WARNING'},
457463
'paramiko': {'level': 'WARNING'},
458464
},
459465
'root': {

viewer/target_loader.py

+59-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from enum import Enum
1010
from pathlib import Path
1111
from tempfile import TemporaryDirectory
12-
from typing import Any, Dict, Iterable, Optional, TypeVar
12+
from typing import Any, Dict, Iterable, List, Optional, TypeVar
1313

1414
import yaml
1515
from celery import Task
@@ -21,6 +21,7 @@
2121
from django.db.models.base import ModelBase
2222
from django.utils import timezone
2323

24+
from api.utils import deployment_mode_is_production
2425
from fragalysis.settings import TARGET_LOADER_MEDIA_DIRECTORY
2526
from scoring.models import SiteObservationGroup
2627
from viewer.models import (
@@ -179,6 +180,51 @@ def _update_task(self, message: str | list) -> None:
179180
pass
180181

181182

183+
def _validate_bundle_against_mode(config_yaml: Dict[str, Any]) -> Optional[str]:
184+
"""Inspects the meta to ensure it is supported by the MODE this stack is in.
185+
Mode is (typically) one of DEVELOPER or PRODUCTION.
186+
"""
187+
assert config_yaml
188+
if not deployment_mode_is_production():
189+
# We're not in production mode - no bundle checks
190+
return None
191+
192+
# PRODUCTION mode (strict)
193+
194+
# Initial concern - the 'xca_version'.
195+
# It must not be 'dirty' and must have a valid 'tag'.
196+
base_error_msg = "Stack is in PRODUCTION mode - and "
197+
try:
198+
xca_version = config_yaml["xca_version"]
199+
except KeyError:
200+
return f"{base_error_msg} 'xca_version' is a required configuration property"
201+
202+
logger.info("xca_version: %s", xca_version)
203+
204+
if "dirty" not in xca_version:
205+
return f"{base_error_msg} 'xca_version' is missing the 'dirty' property"
206+
if xca_version["dirty"]:
207+
return f"{base_error_msg} 'xca_version->dirty' must be False"
208+
209+
if "tag" not in xca_version:
210+
return f"{base_error_msg} 'xca_version' is missing the 'tag' property"
211+
xca_version_tag: str = str(xca_version["tag"])
212+
tag_parts: List[str] = xca_version_tag.split(".")
213+
tag_valid: bool = True
214+
if len(tag_parts) in {2, 3}:
215+
for tag_part in tag_parts:
216+
if not tag_part.isdigit():
217+
tag_valid = False
218+
break
219+
else:
220+
tag_valid = False
221+
if not tag_valid:
222+
return f"{base_error_msg} 'xca_version->tag' must be 'N.N[.N]'. Got '{xca_version_tag}'"
223+
224+
# OK if we get here
225+
return None
226+
227+
182228
def _flatten_dict_gen(d: dict, parent_key: tuple | str | int, depth: int):
183229
for k, v in d.items():
184230
if parent_key:
@@ -1173,10 +1219,19 @@ def process_bundle(self):
11731219
msg = "Missing files in uploaded data, aborting"
11741220
raise FileNotFoundError(msg)
11751221

1222+
# Validate the upload's XCA version information against any MODE-based conditions.
1223+
# An error message is returned if the bundle is not supported.
1224+
if vb_err_msg := _validate_bundle_against_mode(config):
1225+
self.report.log(Level.FATAL, vb_err_msg)
1226+
raise AssertionError(vb_err_msg)
1227+
1228+
# Target (very least) is required
11761229
try:
11771230
self.target_name = config["target_name"]
11781231
except KeyError as exc:
1179-
raise KeyError("target_name missing in config file") from exc
1232+
msg = "target_name missing in config file"
1233+
self.report.log(Level.FATAL, msg)
1234+
raise KeyError(msg) from exc
11801235

11811236
# moved this bit from init
11821237
self.target, target_created = Target.objects.get_or_create(
@@ -1199,7 +1254,7 @@ def process_bundle(self):
11991254
if self._is_already_uploaded(target_created, project_created):
12001255
# remove uploaded file
12011256
Path(self.bundle_path).unlink()
1202-
msg = f"{self.bundle_name} already uploaded, skipping."
1257+
msg = f"{self.bundle_name} already uploaded"
12031258
self.report.final(msg, success=False)
12041259
raise FileExistsError(msg)
12051260

@@ -1217,7 +1272,7 @@ def process_bundle(self):
12171272
self.version_dir = meta["version_dir"]
12181273
self.previous_version_dirs = meta["previous_version_dirs"]
12191274

1220-
# check tranformation matrix files
1275+
# check transformation matrix files
12211276
( # pylint: disable=unbalanced-tuple-unpacking
12221277
trans_neighbourhood,
12231278
trans_conf_site,

0 commit comments

Comments
 (0)