Skip to content

Commit 451f2bf

Browse files
committed
✨(configuration) add configuration Value to support file path in environment
1 parent 582861b commit 451f2bf

File tree

5 files changed

+102
-0
lines changed

5 files changed

+102
-0
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ classifiers = [
2424
]
2525
dependencies = [
2626
"django>=5.0",
27+
"django-configurations>=2.5.1",
2728
"djangorestframework>=3.15.2",
2829
"mozilla-django-oidc>=4.0.1",
2930
"joserfc>=1.0.4",

src/lasuite/configuration/values.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import os
2+
from configurations import values
3+
4+
5+
class SecretFileValue(values.Value):
6+
"""
7+
Class used to interpret value from environment variables with reading file support.
8+
9+
The value set is either (in order of priority):
10+
* The content of the file referenced by the environment variable
11+
`{name}_{file_suffix}` if set.
12+
* The value of the environment variable `{name}` if set.
13+
* The default value
14+
"""
15+
16+
file_suffix = 'FILE'
17+
18+
def __init__(self, *args, **kwargs):
19+
super().__init__(*args, **kwargs)
20+
if 'file_suffix' in kwargs:
21+
self.file_suffix = kwargs['file_suffix']
22+
23+
def setup(self, name):
24+
value = self.default
25+
if self.environ:
26+
full_environ_name = self.full_environ_name(name)
27+
full_environ_name_file = f'{full_environ_name}_{self.file_suffix}'
28+
if full_environ_name_file in os.environ:
29+
filename = os.environ[full_environ_name_file]
30+
if not os.path.exists(filename):
31+
raise ValueError(
32+
'Path {0!r} does not exist.'.format(filename))
33+
try:
34+
file = open(filename, 'r')
35+
value = self.to_python(file.read().removesuffix("\n"))
36+
file.close()
37+
except:
38+
raise ValueError(
39+
'Path {0!r} cannot be read.'.format(filename))
40+
elif full_environ_name in os.environ:
41+
value = self.to_python(os.environ[full_environ_name])
42+
elif self.environ_required:
43+
raise ValueError('Value {0!r} is required to be set as the '
44+
'environment variable {1!r} or {2!r}'
45+
.format(name, full_environ_name_file, full_environ_name))
46+
self.value = value
47+
return value

tests/configuration/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Configuration tests"""

tests/configuration/test_secret

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TestSecretInFile
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""Tests for SecretFileValue"""
2+
3+
import os
4+
5+
from unittest import mock
6+
from lasuite.configuration.values import SecretFileValue
7+
8+
9+
@mock.patch.dict(os.environ, clear=True)
10+
def test_secret_default():
11+
value = SecretFileValue("DefaultTestSecret")
12+
assert value.setup('TEST_SECRET_KEY') == "DefaultTestSecret"
13+
14+
15+
@mock.patch.dict(os.environ, clear=True,
16+
DJANGO_TEST_SECRET_KEY='TestSecretInEnv')
17+
def test_secret_in_env():
18+
value = SecretFileValue("DefaultTestSecret")
19+
assert os.environ["DJANGO_TEST_SECRET_KEY"] == 'TestSecretInEnv'
20+
assert value.setup('TEST_SECRET_KEY') == "TestSecretInEnv"
21+
22+
23+
@mock.patch.dict(os.environ, clear=True,
24+
DJANGO_TEST_SECRET_KEY_FILE=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_secret'))
25+
def test_secret_in_file():
26+
value = SecretFileValue("DefaultTestSecret")
27+
assert os.environ["DJANGO_TEST_SECRET_KEY_FILE"] == os.path.join(
28+
os.path.dirname(os.path.realpath(__file__)), 'test_secret')
29+
assert value.setup('TEST_SECRET_KEY') == "TestSecretInFile"
30+
31+
32+
@mock.patch.dict(os.environ, clear=True)
33+
def test_secret_default_suffix():
34+
value = SecretFileValue("DefaultTestSecret", file_suffix='PATH')
35+
assert value.setup('TEST_SECRET_KEY') == "DefaultTestSecret"
36+
37+
38+
@mock.patch.dict(os.environ, clear=True,
39+
DJANGO_TEST_SECRET_KEY='TestSecretInEnv')
40+
def test_secret_in_env_suffix():
41+
value = SecretFileValue("DefaultTestSecret", file_suffix='PATH')
42+
assert os.environ["DJANGO_TEST_SECRET_KEY"] == 'TestSecretInEnv'
43+
assert value.setup('TEST_SECRET_KEY') == "TestSecretInEnv"
44+
45+
46+
@mock.patch.dict(os.environ, clear=True,
47+
DJANGO_TEST_SECRET_KEY_PATH=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_secret'))
48+
def test_secret_in_file_suffix():
49+
value = SecretFileValue("DefaultTestSecret", file_suffix='PATH')
50+
assert os.environ["DJANGO_TEST_SECRET_KEY_PATH"] == os.path.join(
51+
os.path.dirname(os.path.realpath(__file__)), 'test_secret')
52+
assert value.setup('TEST_SECRET_KEY') == "TestSecretInFile"

0 commit comments

Comments
 (0)