Make SecretsSettingsSource deserialize complex types (#3194)

* Make SecretsSettingsSource deserialize complex types

* Add change notes
This commit is contained in:
David Reed
2021-12-08 14:50:47 -07:00
committed by GitHub
parent 67bfbe3f44
commit a3f180eb2b
3 changed files with 36 additions and 1 deletions
+1
View File
@@ -0,0 +1 @@
Make `SecretsSettingsSource` parse values being assigned to fields of complex types when sourced from a secrets file, just as when sourced from environment variables.
+8 -1
View File
@@ -216,7 +216,14 @@ class SecretsSettingsSource:
for env_name in field.field_info.extra['env_names']:
path = secrets_path / env_name
if path.is_file():
secrets[field.alias] = path.read_text().strip()
secret_value = path.read_text().strip()
if field.is_complex():
try:
secret_value = settings.__config__.json_loads(secret_value)
except ValueError as e:
raise SettingsError(f'error parsing JSON for "{env_name}"') from e
secrets[field.alias] = secret_value
elif path.exists():
warnings.warn(
f'attempted to load secret file "{path}" but found a {path_type(path)} instead.',
+27
View File
@@ -830,6 +830,33 @@ def test_secrets_path_url(tmp_path):
assert Settings().dict() == {'foo': 'http://www.example.com', 'bar': SecretStr('snap')}
def test_secrets_path_json(tmp_path):
p = tmp_path / 'foo'
p.write_text('{"a": "b"}')
class Settings(BaseSettings):
foo: Dict[str, str]
class Config:
secrets_dir = tmp_path
assert Settings().dict() == {'foo': {'a': 'b'}}
def test_secrets_path_invalid_json(tmp_path):
p = tmp_path / 'foo'
p.write_text('{"a": "b"')
class Settings(BaseSettings):
foo: Dict[str, str]
class Config:
secrets_dir = tmp_path
with pytest.raises(SettingsError, match='error parsing JSON for "foo"'):
Settings()
def test_secrets_missing(tmp_path):
class Settings(BaseSettings):
foo: str