fix(secret): uppercase in filename on linux (#3304)

* fix(secret): uppercase in filename

* test(uppercase): fix test

* refactor(secret): apply feedbacks

* refactor(path): apply feedbacks

* fix(test): fix path in test

* cleanup and correct tests

Co-authored-by: Jean Arhancetebehere <jean.arhancetebehere@ubisoft.com>
Co-authored-by: Samuel Colvin <s@muelcolvin.com>
This commit is contained in:
Jean
2022-08-04 18:07:41 +02:00
committed by GitHub
parent ea739fcb22
commit 5293adb3d3
3 changed files with 47 additions and 3 deletions
+1
View File
@@ -0,0 +1 @@
Update `SecretsSettingsSource` to respect `config.case_sensitive`
+18 -3
View File
@@ -269,7 +269,11 @@ class SecretsSettingsSource:
for field in settings.__fields__.values():
for env_name in field.field_info.extra['env_names']:
path = secrets_path / env_name
path = find_case_path(secrets_path, env_name, settings.__config__.case_sensitive)
if not path:
# path does not exist, we curently don't return a warning for this
continue
if path.is_file():
secret_value = path.read_text().strip()
if field.is_complex():
@@ -279,12 +283,11 @@ class SecretsSettingsSource:
raise SettingsError(f'error parsing JSON for "{env_name}"') from e
secrets[field.alias] = secret_value
elif path.exists():
else:
warnings.warn(
f'attempted to load secret file "{path}" but found a {path_type(path)} instead.',
stacklevel=4,
)
return secrets
def __repr__(self) -> str:
@@ -304,3 +307,15 @@ def read_env_file(
return {k.lower(): v for k, v in file_vars.items()}
else:
return file_vars
def find_case_path(dir_path: Path, file_name: str, case_sensitive: bool) -> Optional[Path]:
"""
Find a file within path's directory matching filename, optionally ignoring case.
"""
for f in dir_path.iterdir():
if f.name == file_name:
return f
elif not case_sensitive and f.name.lower() == file_name.lower():
return f
return None
+28
View File
@@ -890,6 +890,33 @@ def test_secrets_path(tmp_path):
assert Settings().dict() == {'foo': 'foo_secret_value_str'}
def test_secrets_case_sensitive(tmp_path):
(tmp_path / 'SECRET_VAR').write_text('foo_env_value_str')
class Settings(BaseSettings):
secret_var: Optional[str]
class Config:
secrets_dir = tmp_path
case_sensitive = True
assert Settings().dict() == {'secret_var': None}
def test_secrets_case_insensitive(tmp_path):
(tmp_path / 'SECRET_VAR').write_text('foo_env_value_str')
class Settings(BaseSettings):
secret_var: Optional[str]
class Config:
secrets_dir = tmp_path
case_sensitive = False
settings = Settings().dict()
assert settings == {'secret_var': 'foo_env_value_str'}
def test_secrets_path_url(tmp_path):
(tmp_path / 'foo').write_text('http://www.example.com')
(tmp_path / 'bar').write_text('snap')
@@ -940,6 +967,7 @@ def test_secrets_missing(tmp_path):
with pytest.raises(ValidationError) as exc_info:
Settings()
assert exc_info.value.errors() == [{'loc': ('foo',), 'msg': 'field required', 'type': 'value_error.missing'}]