Skip to content

Commit 7d75337

Browse files
authored
Merge pull request #1165 from drachenfels-de/fix-project-name-interpolation
Fix `COMPOSE_PROJECT_NAME` interpolation
2 parents 0cf1378 + 65b455f commit 7d75337

5 files changed

+80
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fixed interpolation of the environment variable **COMPOSE_PROJECT_NAME** when it is set from the top-level **name** value within the Compose file.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fixed project name evaluation order to match the order defined in the [compose spec](https://docs.docker.com/compose/how-tos/project-name/#set-a-project-name).

podman_compose.py

+19-13
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,25 @@ def _parse_compose_file(self):
19801980
sys.exit(1)
19811981
content = normalize(content)
19821982
# log(filename, json.dumps(content, indent = 2))
1983+
1984+
# See also https://docs.docker.com/compose/how-tos/project-name/#set-a-project-name
1985+
# **project_name** is initialized to the argument of the `-p` command line flag.
1986+
if not project_name:
1987+
project_name = self.environ.get("COMPOSE_PROJECT_NAME")
1988+
if not project_name:
1989+
project_name = content.get("name")
1990+
if not project_name:
1991+
project_name = dir_basename.lower()
1992+
# More strict then actually needed for simplicity:
1993+
# podman requires [a-zA-Z0-9][a-zA-Z0-9_.-]*
1994+
project_name_normalized = norm_re.sub("", project_name)
1995+
if not project_name_normalized:
1996+
raise RuntimeError(f"Project name [{project_name}] normalized to empty")
1997+
project_name = project_name_normalized
1998+
1999+
self.project_name = project_name
2000+
self.environ.update({"COMPOSE_PROJECT_NAME": self.project_name})
2001+
19832002
content = rec_subs(content, self.environ)
19842003
if isinstance(services := content.get('services'), dict):
19852004
for service in services.values():
@@ -2012,19 +2031,6 @@ def _parse_compose_file(self):
20122031
log.debug(" ** merged:\n%s", json.dumps(compose, indent=2))
20132032
# ver = compose.get('version')
20142033

2015-
if not project_name:
2016-
project_name = compose.get("name")
2017-
if project_name is None:
2018-
# More strict then actually needed for simplicity:
2019-
# podman requires [a-zA-Z0-9][a-zA-Z0-9_.-]*
2020-
project_name = self.environ.get("COMPOSE_PROJECT_NAME", dir_basename.lower())
2021-
project_name = norm_re.sub("", project_name)
2022-
if not project_name:
2023-
raise RuntimeError(f"Project name [{dir_basename}] normalized to empty")
2024-
2025-
self.project_name = project_name
2026-
self.environ.update({"COMPOSE_PROJECT_NAME": self.project_name})
2027-
20282034
services = compose.get("services")
20292035
if services is None:
20302036
services = {}

tests/integration/env-tests/container-compose.yml

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
version: "3"
22

3+
name: my-project-name
4+
35
services:
46
env-test:
57
image: busybox
@@ -8,3 +10,9 @@ services:
810
ZZVAR1: myval1
911
ZZVAR2: 2-$ZZVAR1
1012
ZZVAR3: 3-$ZZVAR2
13+
14+
project-name-test:
15+
image: busybox
16+
command: sh -c "echo $$PNAME"
17+
environment:
18+
PNAME: ${COMPOSE_PROJECT_NAME}

tests/integration/env-tests/test_podman_compose_env.py

+51
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,54 @@ def test_env(self):
3636
compose_yaml_path(),
3737
"down",
3838
])
39+
40+
"""
41+
Tests interpolation of COMPOSE_PROJECT_NAME in the podman-compose config,
42+
which is different from external environment variables because COMPOSE_PROJECT_NAME
43+
is a predefined environment variable generated from the `name` value in the top-level
44+
of the compose.yaml.
45+
46+
See also
47+
- https://docs.docker.com/reference/compose-file/interpolation/
48+
- https://docs.docker.com/reference/compose-file/version-and-name/#name-top-level-element
49+
- https://docs.docker.com/compose/how-tos/environment-variables/envvars/
50+
- https://github.com/compose-spec/compose-spec/blob/main/04-version-and-name.md
51+
"""
52+
53+
def test_project_name(self):
54+
try:
55+
output, _ = self.run_subprocess_assert_returncode([
56+
podman_compose_path(),
57+
"-f",
58+
compose_yaml_path(),
59+
"run",
60+
"project-name-test",
61+
])
62+
self.assertIn("my-project-name", str(output))
63+
finally:
64+
self.run_subprocess_assert_returncode([
65+
podman_compose_path(),
66+
"-f",
67+
compose_yaml_path(),
68+
"down",
69+
])
70+
71+
def test_project_name_override(self):
72+
try:
73+
output, _ = self.run_subprocess_assert_returncode([
74+
podman_compose_path(),
75+
"-f",
76+
compose_yaml_path(),
77+
"run",
78+
"-e",
79+
"COMPOSE_PROJECT_NAME=project-name-override",
80+
"project-name-test",
81+
])
82+
self.assertIn("project-name-override", str(output))
83+
finally:
84+
self.run_subprocess_assert_returncode([
85+
podman_compose_path(),
86+
"-f",
87+
compose_yaml_path(),
88+
"down",
89+
])

0 commit comments

Comments
 (0)