diff --git a/bonfire/bonfire.py b/bonfire/bonfire.py index f57f4d24..1c5c3b2d 100755 --- a/bonfire/bonfire.py +++ b/bonfire/bonfire.py @@ -13,7 +13,7 @@ import bonfire.config as conf from bonfire.local import get_local_apps, get_appsfile_apps -from bonfire.utils import RepoFile +from bonfire.utils import RepoFile, SYNTAX_ERR from bonfire.namespaces import ( Namespace, extend_namespace, @@ -840,6 +840,8 @@ def _get_apps_config(source, target_env, ref_env, local_config_path, local_confi for app_name, app_config in apps_config.items(): for component in app_config["components"]: # validate the config for a component + if not component.get("name"): + raise FatalError(f"{SYNTAX_ERR}, component is missing 'name'") try: RepoFile.from_config(component) except FatalError as err: diff --git a/bonfire/local.py b/bonfire/local.py index a52787a2..446d3f5c 100644 --- a/bonfire/local.py +++ b/bonfire/local.py @@ -60,7 +60,7 @@ def get_local_apps(config): raise FatalError(f"{SYNTAX_ERR}, expected local config to be a dictionary") if "apps" in config: config_apps = _parse_apps_in_cfg(config) - log.info("local app configuration overrides found for: %s", list(config_apps.keys())) + log.info("local configuration found for apps: %s", list(config_apps.keys())) return config_apps diff --git a/tests/test_app_configs.py b/tests/test_app_configs.py index 070aae50..0be975f3 100644 --- a/tests/test_app_configs.py +++ b/tests/test_app_configs.py @@ -197,6 +197,67 @@ def test_local_no_remote_target_apps_found(monkeypatch, source, local_config_met assert actual == _target_apps() +@pytest.mark.parametrize("local_config_method", ("merge", "override")) +@pytest.mark.parametrize("source", (APP_SRE_SRC, FILE_SRC)) +def test_new_local_app_added_to_remote_apps(monkeypatch, source, local_config_method): + local_cfg = { + "apps": [ + { + "name": "appC", + "components": [ + { + "name": "appC_component1", + "host": "gitlab", + "repo": "someorg/somerepo", + "path": "template.yml", + } + ], + } + ] + } + _setup_monkeypatch(monkeypatch, source, local_cfg) + actual = _get_apps_config( + source=source, + target_env="test_target_env", + ref_env=None, + local_config_path="na", + local_config_method=local_config_method, + ) + expected = _target_apps() + expected["appC"] = local_cfg["apps"][0] + assert actual == expected + + +@pytest.mark.parametrize("source", (APP_SRE_SRC, FILE_SRC)) +def test_new_local_component_merged(monkeypatch, source): + local_cfg = { + "apps": [ + { + "name": "appB", + "components": [ + { + "name": "appB_component3", + "host": "gitlab", + "repo": "someorg/somerepo", + "path": "template.yml", + } + ], + } + ] + } + _setup_monkeypatch(monkeypatch, source, local_cfg) + actual = _get_apps_config( + source=source, + target_env="test_target_env", + ref_env=None, + local_config_path="na", + local_config_method="merge", + ) + expected = _target_apps() + expected["appB"]["components"].append(local_cfg["apps"][0]["components"][0]) + assert actual == expected + + @pytest.mark.parametrize("local_config_method", ("merge", "override")) @pytest.mark.parametrize("source", (APP_SRE_SRC, FILE_SRC)) def test_empty_local_config(monkeypatch, source, local_config_method): @@ -269,10 +330,6 @@ def test_local_config_merge(monkeypatch, source): { "name": "appB", "components": [ - { - "name": "appBcomponent1", - "ref": "a_new_ref", - }, { "name": "appBcomponent2", "parameters": { @@ -280,6 +337,12 @@ def test_local_config_merge(monkeypatch, source): "NEW_PARAM2": "NEW_VALUE2", }, }, + # intentionally reversing order of components... + { + "name": "appBcomponent1", + "repo": "neworg/newrepo", + "ref": "a_new_ref", + }, ], }, ] @@ -300,6 +363,7 @@ def test_local_config_merge(monkeypatch, source): for component in app_config["components"]: if component["name"] == "appBcomponent1": component["ref"] = "a_new_ref" + component["repo"] = "neworg/newrepo" if component["name"] == "appBcomponent2": component["parameters"] = { "EXISTING_PARAM1": "EXISTING_VALUE1",