Split database config into DATABASE_* components
CI / Build and push docker image (push) Successful in 2m56s
CI / Build and push docker image (push) Successful in 2m56s
Assemble the Postgres DSN from DATABASE_ENGINE/HOST/PORT/NAME/USER/ PASSWORD/OPTIONS so only the password needs to live in a secret; the rest can go in a ConfigMap. DATABASE_URL remains a full-DSN override (used by the sqlite test suite). Credentials are percent-encoded, the port and options are omitted when empty, and the k8s migrate initContainer now also reads the config ConfigMap.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
"""Unit tests for the database DSN assembly in :mod:`tavolo.config`.
|
||||
|
||||
``Settings.from_env`` is called directly with a fully replaced
|
||||
``os.environ`` so no test leaks its ``DATABASE_*`` overrides into the
|
||||
suite (``tests/__init__.py`` sets ``DATABASE_URL=sqlite://:memory:``
|
||||
globally for the application tests).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from tavolo.config import Settings
|
||||
|
||||
|
||||
def _settings(env: dict) -> Settings:
|
||||
with patch.dict(os.environ, env, clear=True):
|
||||
return Settings.from_env()
|
||||
|
||||
|
||||
class DatabaseUrlTests(unittest.TestCase):
|
||||
def test_defaults_assemble_from_parts(self):
|
||||
settings = _settings({})
|
||||
self.assertEqual(
|
||||
settings.database_url,
|
||||
"postgres://tavolo:password@localhost/tavolo",
|
||||
)
|
||||
|
||||
def test_components_override_defaults(self):
|
||||
settings = _settings({
|
||||
"DATABASE_ENGINE": "postgres",
|
||||
"DATABASE_HOST": "db.internal",
|
||||
"DATABASE_PORT": "5433",
|
||||
"DATABASE_NAME": "cards",
|
||||
"DATABASE_USER": "scopa",
|
||||
"DATABASE_PASSWORD": "s3cret",
|
||||
})
|
||||
self.assertEqual(
|
||||
settings.database_url,
|
||||
"postgres://scopa:s3cret@db.internal:5433/cards",
|
||||
)
|
||||
|
||||
def test_options_are_appended_as_query_string(self):
|
||||
settings = _settings({"DATABASE_OPTIONS": "ssl=require"})
|
||||
self.assertEqual(
|
||||
settings.database_url,
|
||||
"postgres://tavolo:password@localhost/tavolo?ssl=require",
|
||||
)
|
||||
|
||||
def test_options_leading_question_mark_is_stripped(self):
|
||||
settings = _settings({"DATABASE_OPTIONS": "?ssl=require"})
|
||||
self.assertEqual(
|
||||
settings.database_url,
|
||||
"postgres://tavolo:password@localhost/tavolo?ssl=require",
|
||||
)
|
||||
|
||||
def test_credentials_are_percent_encoded(self):
|
||||
settings = _settings({
|
||||
"DATABASE_USER": "u@x",
|
||||
"DATABASE_PASSWORD": "p@ss/word:1",
|
||||
})
|
||||
self.assertEqual(
|
||||
settings.database_url,
|
||||
"postgres://u%40x:p%40ss%2Fword%3A1@localhost/tavolo",
|
||||
)
|
||||
|
||||
def test_database_url_takes_precedence_over_parts(self):
|
||||
settings = _settings({
|
||||
"DATABASE_URL": "sqlite://:memory:",
|
||||
"DATABASE_HOST": "db.internal",
|
||||
"DATABASE_PASSWORD": "ignored",
|
||||
})
|
||||
self.assertEqual(settings.database_url, "sqlite://:memory:")
|
||||
|
||||
def test_empty_database_url_falls_back_to_parts(self):
|
||||
settings = _settings({"DATABASE_URL": ""})
|
||||
self.assertEqual(
|
||||
settings.database_url,
|
||||
"postgres://tavolo:password@localhost/tavolo",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user