Skip to content

Commit

Permalink
Warn on potential configuration errors with multiple databases
Browse files Browse the repository at this point in the history
* DEFAULT_DATABASE_URL as well as DATABASE_URL
* not_all_uppercase_DATABASE_URL
  • Loading branch information
doismellburning committed Mar 2, 2015
1 parent 2200737 commit b349d54
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
29 changes: 25 additions & 4 deletions django12factor/__init__.py
Expand Up @@ -74,12 +74,33 @@ def factorise(custom_settings=None):
'default': dj_database_url.config(default='sqlite://:memory:')
}

for (potential_database_url, value) in six.iteritems(os.environ):
for (key, value) in six.iteritems(os.environ):
_SUFFIX = "_DATABASE_URL"
_OFFSET = len(_SUFFIX)
if potential_database_url.endswith(_SUFFIX):
dbname = potential_database_url[:-_OFFSET].lower()
db = dj_database_url.parse(os.environ[potential_database_url])

if key.endswith(_SUFFIX):
prefix = key[:-_OFFSET]

if prefix != prefix.upper():
# i.e. it was not already all upper-cased
logger.warn(
"Not parsing %s as a database url because the "
"prefix (%s) was not all upper-case - django12factor "
"will convert prefixes to lower-case for use as database "
"names" % (key, prefix))
continue

dbname = key[:-_OFFSET].lower()

if dbname == "default" and 'DATABASE_URL' in os.environ:
logger.warn(
"You have set the environment variables DATABASE_URL "
"_and_ {key}, both of which would configure "
"`DATABASES['default']`. {key} is being "
"ignored.".format(key=key))
continue

db = dj_database_url.parse(os.environ[key])
settings['DATABASES'][dbname] = db

settings['DEBUG'] = getenv_bool('DEBUG')
Expand Down
39 changes: 39 additions & 0 deletions tests/test_d12f.py
Expand Up @@ -85,3 +85,42 @@ def test_multiple_db_support(self):
"variable %s" % (DBNAME, DB_URL_NAME)
)
self.assertIn('postgres', dbs[DBNAME]['ENGINE'])

def test_multiple_default_databases(self):
"""
Ensure if DEFAULT_DATABASE_URL and DATABASE_URL are set, latter wins.
"""

IGNORED_DB_NAME = "should_be_ignored"
DATABASE_URL = "postgres://username:password@host:1234/dbname"
IGNORED = "postgres://username:password@host:1234/%s" % IGNORED_DB_NAME

with debugenv(DATABASE_URL=DATABASE_URL, DEFAULT_DATABASE_URL=IGNORED):
default_db = d12f()['DATABASES']['default']
self.assertNotEquals(
default_db['NAME'],
IGNORED_DB_NAME,
"Parsed the contents of DEFAULT_DATABASE_URL instead of "
"ignoring it in favour of DATABASE_URL"
)

def test_non_capitalised_database_ignored(self):
"""
Ensure "malformed" X_DATABASE_URLs aren't parsed.
"""

e = {
'invalid_DATABASE_URL': "",
'AlsoInValid_DATABASE_URL': "",
'ALMOST_CORRECt_DATABASE_URL': "",
}

with debugenv(**e):
dbs = d12f()['DATABASES']

self.assertEquals(
len(dbs),
1,
"Loaded %d databases instead of just 1 (default) - got %s "
"from environment %s" % (len(dbs), dbs.keys(), e)
)

0 comments on commit b349d54

Please sign in to comment.