mirror of
https://github.com/containers/podman-compose.git
synced 2025-08-09 13:54:59 +02:00
Implement environment variable interpolation to YAML dictionary keys
`podman-compose` currently does not support interpolating environment variables in dictionary keys, despite the compose file specification indicating this capability. See the relevant compose-spec documentation: https://github.com/compose-spec/compose-spec/blob/main/12-interpolation.md This feature is useful in `labels` or `environment` sections, where keys can be user-defined strings. To enable interpolation, an alternate equal sign syntax must be used, e.g.: services: foo: labels: - "$VAR_NAME=label_value" After this PR `podman-compose` will align more closely with the compose file specification, allowing for the interpolation of environment variables in dictionary keys. Signed-off-by: Monika Kairaityte <monika@kibit.lt>
This commit is contained in:
1
newsfragments/env-var-interpolation-for-keys.feature
Normal file
1
newsfragments/env-var-interpolation-for-keys.feature
Normal file
@ -0,0 +1 @@
|
||||
Add support for environment variable interpolation for YAML keys.
|
@ -290,7 +290,7 @@ def rec_subs(value: dict | str | Iterable, subs_dict: dict[str, Any]) -> dict |
|
||||
svc_envs = rec_subs(svc_envs, subs_dict)
|
||||
subs_dict.update(svc_envs)
|
||||
|
||||
value = {k: rec_subs(v, subs_dict) for k, v in value.items()}
|
||||
value = {rec_subs(k, subs_dict): rec_subs(v, subs_dict) for k, v in value.items()}
|
||||
elif isinstance(value, str):
|
||||
|
||||
def convert(m: re.Match) -> str:
|
||||
|
@ -1 +1,2 @@
|
||||
DOT_ENV_VARIABLE=This value is from the .env file
|
||||
TEST_LABELS=TEST
|
||||
|
@ -11,4 +11,10 @@ services:
|
||||
EXAMPLE_DOT_ENV: $DOT_ENV_VARIABLE
|
||||
EXAMPLE_LITERAL: This is a $$literal
|
||||
EXAMPLE_EMPTY: $NOT_A_VARIABLE
|
||||
labels_test:
|
||||
image: busybox
|
||||
labels:
|
||||
- "$TEST_LABELS=test_labels"
|
||||
- test.${TEST_LABELS}=${TEST_LABELS}
|
||||
- "${TEST_LABELS}.test2=test2(`${TEST_LABELS}`)"
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
import json
|
||||
import os
|
||||
import unittest
|
||||
|
||||
@ -36,6 +37,18 @@ class TestComposeInterpolation(unittest.TestCase, RunSubprocessMixin):
|
||||
self.assertIn("EXAMPLE_DOT_ENV='This value is from the .env file'", str(output))
|
||||
self.assertIn("EXAMPLE_EMPTY=''", str(output))
|
||||
self.assertIn("EXAMPLE_LITERAL='This is a $literal'", str(output))
|
||||
|
||||
output, _ = self.run_subprocess_assert_returncode([
|
||||
"podman",
|
||||
"inspect",
|
||||
"interpolation_labels_test_1",
|
||||
])
|
||||
inspect_output = json.loads(output)
|
||||
labels_dict = inspect_output[0].get("Config", {}).get("Labels", {})
|
||||
self.assertIn(('TEST', 'test_labels'), labels_dict.items())
|
||||
self.assertIn(('TEST.test2', 'test2(`TEST`)'), labels_dict.items())
|
||||
self.assertIn(('test.TEST', 'TEST'), labels_dict.items())
|
||||
|
||||
finally:
|
||||
self.run_subprocess_assert_returncode([
|
||||
podman_compose_path(),
|
||||
|
@ -71,3 +71,34 @@ class TestRecSubs(unittest.TestCase):
|
||||
sub_dict = {"v1": "high priority", "empty": ""}
|
||||
result = rec_subs(input, sub_dict)
|
||||
self.assertEqual(result, expected, msg=desc)
|
||||
|
||||
def test_env_var_substitution_in_dictionary_keys(self) -> None:
|
||||
sub_dict = {"NAME": "TEST1", "NAME2": "TEST2"}
|
||||
input = {
|
||||
'services': {
|
||||
'test': {
|
||||
'image': 'busybox',
|
||||
'labels': {
|
||||
'$NAME and ${NAME2}': '${NAME2} and $NAME',
|
||||
'test1.${NAME}': 'test1',
|
||||
'$NAME': '${NAME2}',
|
||||
'${NAME}.test2': 'Host(`${NAME2}`)',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
result = rec_subs(input, sub_dict)
|
||||
expected = {
|
||||
'services': {
|
||||
'test': {
|
||||
'image': 'busybox',
|
||||
'labels': {
|
||||
'TEST1 and TEST2': 'TEST2 and TEST1',
|
||||
'test1.TEST1': 'test1',
|
||||
'TEST1': 'TEST2',
|
||||
'TEST1.test2': 'Host(`TEST2`)',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
self.assertEqual(result, expected)
|
||||
|
Reference in New Issue
Block a user