From 36ef2d6dc735c9134afaf6707304ade08255cb42 Mon Sep 17 00:00:00 2001 From: Livio Ribeiro Date: Tue, 16 Apr 2024 07:35:20 -0300 Subject: [PATCH] activate multiple profiles (#45) * add activation of multiple profiles --- docs/configuration.md | 5 ++++ src/selva/configuration/settings.py | 7 +++-- .../configuration/application_prd.yaml | 2 +- .../configuration/settings.yaml | 0 .../configuration/settings_dev.yaml | 1 + .../configuration/settings_prd.yaml | 1 + .../configuration/settings_stg.yaml | 1 + .../profiles/configuration/settings_dev.yaml | 2 +- .../profiles/configuration/settings_prd.yaml | 2 +- .../profiles/configuration/settings_stg.yaml | 2 +- tests/configuration/test_settings.py | 29 ++++++++++++++----- 11 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 tests/configuration/multiple_profiles/configuration/settings.yaml create mode 100644 tests/configuration/multiple_profiles/configuration/settings_dev.yaml create mode 100644 tests/configuration/multiple_profiles/configuration/settings_prd.yaml create mode 100644 tests/configuration/multiple_profiles/configuration/settings_stg.yaml diff --git a/docs/configuration.md b/docs/configuration.md index cfff5b6..ca3338f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -97,6 +97,11 @@ As an example, if we define `SELVA_PROFILE=dev`, the file `settings_dev.yaml` wi be loaded. If instead we define `SELVA_PROFILE=prod`, then the file `settings_prod.yaml` will be loaded. +Multiple profiles can be activated by setting `SELVA_PROFILE` with a comma separated +list of profiles, for example `SELVA_PROFILE=dev,prod`. The framework will iterate +over the list and merge the settings found on each one. The precedence is from last +to first, so settings from one profile overwrite settings from the previous ones. + ## Environment variables Settings can also be defined with environment variables whose names start with `SELVA__`, diff --git a/src/selva/configuration/settings.py b/src/selva/configuration/settings.py index d0930df..e0a4b9e 100644 --- a/src/selva/configuration/settings.py +++ b/src/selva/configuration/settings.py @@ -92,9 +92,10 @@ def _get_settings_nocache() -> Settings: # merge with main settings file (settings.yaml) merge_recursive(settings, get_settings_for_profile()) - # merge with environment settings file (settings_$SELVA_PROFILE.yaml) - if active_profile := os.getenv(SELVA_PROFILE): - merge_recursive(settings, get_settings_for_profile(active_profile)) + # merge with profile settings files (settings_$SELVA_PROFILE.yaml) + if active_profile_list := os.getenv(SELVA_PROFILE): + for active_profile in (p.strip() for p in active_profile_list.split(",")): + merge_recursive(settings, get_settings_for_profile(active_profile)) # merge with environment variables (SELVA_*) from_env_vars = parse_settings_from_env(os.environ) diff --git a/tests/configuration/alternate/configuration/application_prd.yaml b/tests/configuration/alternate/configuration/application_prd.yaml index ee56c26..d23d6b9 100644 --- a/tests/configuration/alternate/configuration/application_prd.yaml +++ b/tests/configuration/alternate/configuration/application_prd.yaml @@ -1 +1 @@ -environment: prd \ No newline at end of file +profile: prd \ No newline at end of file diff --git a/tests/configuration/multiple_profiles/configuration/settings.yaml b/tests/configuration/multiple_profiles/configuration/settings.yaml new file mode 100644 index 0000000..e69de29 diff --git a/tests/configuration/multiple_profiles/configuration/settings_dev.yaml b/tests/configuration/multiple_profiles/configuration/settings_dev.yaml new file mode 100644 index 0000000..7120f47 --- /dev/null +++ b/tests/configuration/multiple_profiles/configuration/settings_dev.yaml @@ -0,0 +1 @@ +profile_dev: true diff --git a/tests/configuration/multiple_profiles/configuration/settings_prd.yaml b/tests/configuration/multiple_profiles/configuration/settings_prd.yaml new file mode 100644 index 0000000..1886483 --- /dev/null +++ b/tests/configuration/multiple_profiles/configuration/settings_prd.yaml @@ -0,0 +1 @@ +profile_prd: true diff --git a/tests/configuration/multiple_profiles/configuration/settings_stg.yaml b/tests/configuration/multiple_profiles/configuration/settings_stg.yaml new file mode 100644 index 0000000..50a094f --- /dev/null +++ b/tests/configuration/multiple_profiles/configuration/settings_stg.yaml @@ -0,0 +1 @@ +profile_stg: true \ No newline at end of file diff --git a/tests/configuration/profiles/configuration/settings_dev.yaml b/tests/configuration/profiles/configuration/settings_dev.yaml index 2713f19..88de559 100644 --- a/tests/configuration/profiles/configuration/settings_dev.yaml +++ b/tests/configuration/profiles/configuration/settings_dev.yaml @@ -1 +1 @@ -environment: dev +profile: dev diff --git a/tests/configuration/profiles/configuration/settings_prd.yaml b/tests/configuration/profiles/configuration/settings_prd.yaml index 4c0f335..49efcfd 100644 --- a/tests/configuration/profiles/configuration/settings_prd.yaml +++ b/tests/configuration/profiles/configuration/settings_prd.yaml @@ -1 +1 @@ -environment: prd +profile: prd diff --git a/tests/configuration/profiles/configuration/settings_stg.yaml b/tests/configuration/profiles/configuration/settings_stg.yaml index 2daa011..9630a36 100644 --- a/tests/configuration/profiles/configuration/settings_stg.yaml +++ b/tests/configuration/profiles/configuration/settings_stg.yaml @@ -1 +1 @@ -environment: stg +profile: stg \ No newline at end of file diff --git a/tests/configuration/test_settings.py b/tests/configuration/test_settings.py index 08d519e..b768870 100644 --- a/tests/configuration/test_settings.py +++ b/tests/configuration/test_settings.py @@ -41,7 +41,22 @@ def test_get_settings_with_profile(monkeypatch, profile): result = _get_settings_nocache() assert result == default_settings | { "name": "application", - "environment": profile, + "profile": profile, + } + + +@pytest.mark.parametrize( + ["profile_a", "profile_b"], + [["dev", "stg"], ["stg", "prd"], ["prd", "dev"]], +) +def test_get_settings_with_multiple_profiles(monkeypatch, profile_a, profile_b): + monkeypatch.chdir(Path(__file__).parent / "multiple_profiles") + monkeypatch.setenv("SELVA_PROFILE", f"{profile_a}, {profile_b}") + + result = _get_settings_nocache() + assert result == default_settings | { + f"profile_{profile_a}": True, + f"profile_{profile_b}": True, } @@ -49,9 +64,9 @@ def test_get_settings_with_profile(monkeypatch, profile): "profile,expected", [ (None, {"name": "application"}), - ("dev", {"environment": "dev"}), - ("stg", {"environment": "stg"}), - ("prd", {"environment": "prd"}), + ("dev", {"profile": "dev"}), + ("stg", {"profile": "stg"}), + ("prd", {"profile": "prd"}), ], ids=["None", "dev", "stg", "prd"], ) @@ -145,7 +160,7 @@ def test_configure_settings_file_with_profile(monkeypatch): result = _get_settings_nocache() assert result == default_settings | { - "environment": "prd", + "profile": "prd", "prop": "value", "list": ["1", "2", "3"], "dict": { @@ -170,7 +185,7 @@ def test_configure_env_setttings(monkeypatch, env): result = _get_settings_nocache() assert result == default_settings | { "name": "application", - "environment": env, + "profile": env, } @@ -213,7 +228,7 @@ def test_setttings_class_env(monkeypatch, env): settings = _get_settings_nocache() assert settings["name"] == "application" - assert settings["environment"] == env + assert settings["profile"] == env def test_no_profile_settings_file_should_log_warning(monkeypatch, caplog):