podman-compose
podman-compose copied to clipboard
Environment interpolation replacement string
Describe the bug
As described in docker docks https://docs.docker.com/compose/environment-variables/env-file/#interpolation there is an extra form that should be supported in docker-compose.yml file: ${VAR_NAME:+replacement}
To Reproduce
services:
variables:
image: busybox
command: ["/bin/busybox", "sh", "-c", "export | grep EXAMPLE"]
environment:
EXAMPLE_REPLACE: ${USER+replaced}
Expected behavior
EXAMPLE_REPLACE=replaced
Actual behavior
EXAMPLE_REPLACE='${USER+replaced}'
Output
$ podman-compose version
using podman version: 4.8.1
podman-compose version 1.0.6
podman --version
podman version 4.8.1
...
Environment:
- OS: Linux / WSL / Mac
- podman version: 4.8.1
- podman compose version: 1.0.6
Additional context Patch:
Index: podman_compose.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/podman_compose.py b/podman_compose.py
--- a/podman_compose.py (revision bce40c2db30fb0ffb9264b5f51535c26f48fe983)
+++ b/podman_compose.py (date 1702366787909)
@@ -251,6 +251,8 @@
# ${VARIABLE-default} default if not set
# ${VARIABLE:?err} raise error if not set or empty
# ${VARIABLE?err} raise error if not set
+# ${VARIABLE:+replace} replace if set and not empty
+# ${VARIABLE+replace} replace if set
# $$ means $
var_re = re.compile(
@@ -262,6 +264,7 @@
(?P<braced>[_a-zA-Z][_a-zA-Z0-9]*)
(?:(?P<empty>:)?(?:
(?:-(?P<default>[^}]*)) |
+ (?:+(?P<replace>[^}]*)) |
(?:\?(?P<err>[^}]*))
))?
})
@@ -287,7 +290,7 @@
if value == "" and m.group("empty"):
value = None
if value is not None:
- return str(value)
+ return str(value) if not m.group("replace") else m.group("replace")
if m.group("err") is not None:
raise RuntimeError(m.group("err"))
return m.group("default") or ""
I would add to this the possibility of nested environment variables substitution for situations like ${VARIABLE:-${VARIABLE:-default}}
Patch:
@@ -248,7 +248,11 @@
# $VARIABLE
# ${VARIABLE}
# ${VARIABLE:-default} default if not set or empty
+# ${VARIABLE:-${VARIABLE:-default | +replace | ?err}}
# ${VARIABLE-default} default if not set
+# ${VARIABLE-${VARIABLE:-default | +replace | ?err}}
+# ${VARIABLE:+replace} replace if set and not empty
+# ${VARIABLE+replace} replace if set
# ${VARIABLE:?err} raise error if not set or empty
# ${VARIABLE?err} raise error if not set
# $$ means $
@@ -262,6 +266,7 @@
(?P<braced>[_a-zA-Z][_a-zA-Z0-9]*)
(?:(?P<empty>:)?(?:
(?:-(?P<default>[^}]*)) |
+ (?:\+(?P<replace>[^}]*)) |
(?:\?(?P<err>[^}]*))
))?
})
@@ -287,12 +292,14 @@
if value == "" and m.group("empty"):
value = None
if value is not None:
- return str(value)
+ return str(value) if not m.group("replace") else m.group("replace")
if m.group("err") is not None:
raise RuntimeError(m.group("err"))
return m.group("default") or ""
value = var_re.sub(convert, value)
+ # iterate a second time for nested environment variables for default values:
+ value = var_re.sub(convert, value)
elif hasattr(value, "__iter__"):
value = [rec_subs(i, subs_dict) for i in value]
return value
I would add to this the possibility of nested environment variables substitution for situations like
${VARIABLE:-${VARIABLE:-default}}
Good point. Unfortunately I don't have the time to come up with a possible solution to support nested variable expansion, less so to create a PR. Would there be any takers?
@mfloresVicomtech, if we are to get into the nitty-gritty of it, then we would also need to update how .env files are being read:
SUBJECT=$USER
MESSAGE=${GREETING:+$GREETING ${SUBJECT}}
docker-compose would read that as SUBJECT=my-user-name and given a GREETING=Hello - MESSAGE="Hello my-user-name".
Whereas podman-compose due to python-dotenv (environs behaves exactly the same) - would fail to expand any variables at all in this scenario! (Compare it to dotenv on npm - doesn't even attempt to expand any variables whatsoever)
please open a PR
Whereas podman-compose due to python-dotenv (environs behaves exactly the same)
dotent is completely different concern docker-compose v1.x (the python version) was using same library
https://github.com/docker/compose/blob/1.28.x/requirements.txt#L16
please don't mix
- substitution inside compose yaml
- and substitution inside .env
- and substitution inside envfile