From 915b628094968c0bda21052b897d7c9a9100f249 Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Wed, 6 May 2026 00:28:11 +0200 Subject: [PATCH] feat: support nested env destination paths --- apps/utils/docker/compose.py | 26 +++++++++++++++++---- tests/test_compose.py | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/apps/utils/docker/compose.py b/apps/utils/docker/compose.py index e8cc874..ea116ca 100644 --- a/apps/utils/docker/compose.py +++ b/apps/utils/docker/compose.py @@ -140,7 +140,6 @@ def _delete_unset_integration_env_keys(compose, greffon_info): ] return compose - def _compute_instance_context(greffon_info): """Expose instance_url / instance_host / instance_port / instance_id to the Jinja render context so catalog metadata default_value strings can @@ -194,6 +193,24 @@ def create_volumes_then_copy_files(greffon_info): docker_create_volume(volume) docker_copy_file_into_volume(volume) +def _get_destination_value(configuration_value, destination): + if not isinstance(configuration_value, dict): + return '' + + value_path = destination.get('value_path') + if not value_path: + return configuration_value.get('value', '') + + current = configuration_value + for part in value_path.split('.'): + if not isinstance(current, dict): + return '' + current = current.get(part, '') + + if current is None: + return '' + return current + def apply_configuration(greffon_info, compose): for configuration in greffon_info.get('configurations', []): for destination in configuration.get('destinations', []): @@ -209,10 +226,11 @@ def apply_configuration(greffon_info, compose): elif destination['type'] == 'env': remove_compose_file(greffon_info) compose['services'][destination['container']].setdefault('environment', []) + env_value = _get_destination_value(configuration.get('value'), destination) if isinstance(compose['services'][destination['container']]['environment'], dict): - compose['services'][destination['container']]['environment'][destination['key']] = configuration['value'].get('value', '') + compose['services'][destination['container']]['environment'][destination['key']] = env_value else: - compose['services'][destination['container']]['environment'].append(f'{destination["key"]}={configuration["value"].get("value", "")}') + compose['services'][destination['container']]['environment'].append(f'{destination["key"]}={env_value}') elif destination['type'] == 'file': remove_compose_file(greffon_info) file_path = os.path.join(get_greffon_path(greffon_info), destination['name']) @@ -261,4 +279,4 @@ def get_status(greffon_id): return { 'status': status, 'containers': containers - } \ No newline at end of file + } diff --git a/tests/test_compose.py b/tests/test_compose.py index 2456025..f83aa5d 100644 --- a/tests/test_compose.py +++ b/tests/test_compose.py @@ -182,6 +182,51 @@ def test_apply_configuration_env(self, mock_remove, mock_client): self.assertIn('environment', compose['services']['app']) self.assertIn('DB_HOST=my_db_host', compose['services']['app']['environment']) + @patch('apps.utils.docker.compose.client') + @patch('apps.utils.docker.compose.remove_compose_file') + def test_apply_configuration_env_value_path(self, mock_remove, mock_client): + """Env destination: extract a nested value with destination.value_path.""" + from apps.utils.docker.compose import apply_configuration + + greffon_info = { + 'id': 'test-env-nested', + 'configurations': [ + { + 'value': { + 'runner_scope': 'org', + 'target': { + 'org_name': 'greffon', + }, + }, + 'destinations': [ + { + 'type': 'env', + 'container': 'app', + 'key': 'RUNNER_SCOPE', + 'value_path': 'runner_scope', + }, + { + 'type': 'env', + 'container': 'app', + 'key': 'ORG_NAME', + 'value_path': 'target.org_name', + }, + ], + } + ], + 'volumes': {}, + } + compose = { + 'services': { + 'app': {} + } + } + + apply_configuration(greffon_info, compose) + + self.assertIn('RUNNER_SCOPE=org', compose['services']['app']['environment']) + self.assertIn('ORG_NAME=greffon', compose['services']['app']['environment']) + @patch('apps.utils.docker.compose.client') @patch('apps.utils.docker.compose.remove_compose_file') @patch('apps.utils.docker.compose.DataURI')