From 4c270b9116503c08587289e4f12144053c6b6613 Mon Sep 17 00:00:00 2001 From: Ari Pollak Date: Fri, 1 Mar 2024 16:13:36 -0500 Subject: [PATCH 1/3] Allow run/exec -e with equals sign in value Fixes: #798 Signed-off-by: Ari Pollak --- podman_compose.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/podman_compose.py b/podman_compose.py index 702a5d6..a7bd569 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -2466,7 +2466,7 @@ async def compose_run(compose, args): cnt["working_dir"] = args.workdir env = dict(cnt.get("environment", {})) if args.env: - additional_env_vars = dict(map(lambda each: each.split("="), args.env)) + additional_env_vars = dict(map(lambda each: each.split("=", maxsplit=1), args.env)) env.update(additional_env_vars) cnt["environment"] = env if not args.service_ports: @@ -2514,7 +2514,7 @@ async def compose_exec(compose, args): env = dict(cnt.get("environment", {})) if args.env: additional_env_vars = dict( - map(lambda each: each.split("=") if "=" in each else (each, None), args.env) + map(lambda each: each.split("=", maxsplit=1) if "=" in each else (each, None), args.env) ) env.update(additional_env_vars) for name, value in env.items(): From c4fa8f7a168ee77f8a5b89e8713c2248b12e9e65 Mon Sep 17 00:00:00 2001 From: Ari Pollak Date: Sat, 9 Mar 2024 15:52:46 -0500 Subject: [PATCH 2/3] Split exec args parsing into new function and add unit tests for it Signed-off-by: Ari Pollak --- podman_compose.py | 9 ++++-- pytests/test_compose_exec_args.py | 46 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 pytests/test_compose_exec_args.py diff --git a/podman_compose.py b/podman_compose.py index a7bd569..2b4dcbe 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -2502,6 +2502,12 @@ async def compose_exec(compose, args): container_names = compose.container_names_by_service[args.service] container_name = container_names[args.index - 1] cnt = compose.container_by_name[container_name] + podman_args = compose_exec_args(cnt, container_name, args) + p = await compose.podman.run([], "exec", podman_args) + sys.exit(p) + + +def compose_exec_args(cnt, container_name, args): podman_args = ["--interactive"] if args.privileged: podman_args += ["--privileged"] @@ -2522,8 +2528,7 @@ async def compose_exec(compose, args): podman_args += [container_name] if args.cnt_command is not None and len(args.cnt_command) > 0: podman_args += args.cnt_command - p = await compose.podman.run([], "exec", podman_args) - sys.exit(p) + return podman_args async def transfer_service_status(compose, args, action): diff --git a/pytests/test_compose_exec_args.py b/pytests/test_compose_exec_args.py new file mode 100644 index 0000000..93f3e4b --- /dev/null +++ b/pytests/test_compose_exec_args.py @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0 + +import argparse +import unittest + +from podman_compose import compose_exec_args + + +class TestExecArgs(unittest.TestCase): + def test_minimal(self): + cnt = get_minimal_container() + args = get_minimal_args() + + result = compose_exec_args(cnt, "container_name", args) + expected = ["--interactive", "--tty", "container_name"] + self.assertEqual(result, expected) + + def test_additional_env_value_equals(self): + cnt = get_minimal_container() + args = get_minimal_args() + args.env = ["key=valuepart1=valuepart2"] + + result = compose_exec_args(cnt, "container_name", args) + expected = [ + "--interactive", + "--tty", + "--env", + "key=valuepart1=valuepart2", + "container_name", + ] + self.assertEqual(result, expected) + + +def get_minimal_container(): + return {} + + +def get_minimal_args(): + return argparse.Namespace( + T=None, + cnt_command=None, + env=None, + privileged=None, + user=None, + workdir=None, + ) From f2f5483a746f71b8875f35caf55b9db4a1759760 Mon Sep 17 00:00:00 2001 From: Ari Pollak Date: Sat, 9 Mar 2024 16:17:38 -0500 Subject: [PATCH 3/3] Extract compose_run args parsing and add unit tests Signed-off-by: Ari Pollak --- podman_compose.py | 20 ++++--- ..._compose_run_update_container_from_args.py | 60 +++++++++++++++++++ 2 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 pytests/test_compose_run_update_container_from_args.py diff --git a/podman_compose.py b/podman_compose.py index 2b4dcbe..a93c692 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -2455,6 +2455,18 @@ async def compose_run(compose, args): ) await compose.commands["build"](compose, build_args) + compose_run_update_container_from_args(compose, cnt, args) + # run podman + podman_args = await container_to_args(compose, cnt, args.detach) + if not args.detach: + podman_args.insert(1, "-i") + if args.rm: + podman_args.insert(1, "--rm") + p = await compose.podman.run([], "run", podman_args) + sys.exit(p) + + +def compose_run_update_container_from_args(compose, cnt, args): # adjust one-off container options name0 = "{}_{}_tmp{}".format(compose.project_name, args.service, random.randrange(0, 65536)) cnt["name"] = args.name or name0 @@ -2486,14 +2498,6 @@ async def compose_run(compose, args): # can't restart and --rm if args.rm and "restart" in cnt: del cnt["restart"] - # run podman - podman_args = await container_to_args(compose, cnt, args.detach) - if not args.detach: - podman_args.insert(1, "-i") - if args.rm: - podman_args.insert(1, "--rm") - p = await compose.podman.run([], "run", podman_args) - sys.exit(p) @cmd_run(podman_compose, "exec", "execute a command in a running container") diff --git a/pytests/test_compose_run_update_container_from_args.py b/pytests/test_compose_run_update_container_from_args.py new file mode 100644 index 0000000..6712bd1 --- /dev/null +++ b/pytests/test_compose_run_update_container_from_args.py @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0 + +import argparse +import unittest + +from podman_compose import PodmanCompose +from podman_compose import compose_run_update_container_from_args + + +class TestRunArgs(unittest.TestCase): + def test_minimal(self): + cnt = get_minimal_container() + compose = get_minimal_compose() + args = get_minimal_args() + + compose_run_update_container_from_args(compose, cnt, args) + + expected_cnt = {"name": "default_name", "tty": True} + self.assertEqual(cnt, expected_cnt) + + def test_additional_env_value_equals(self): + cnt = get_minimal_container() + compose = get_minimal_compose() + args = get_minimal_args() + args.env = ["key=valuepart1=valuepart2"] + + compose_run_update_container_from_args(compose, cnt, args) + + expected_cnt = { + "environment": { + "key": "valuepart1=valuepart2", + }, + "name": "default_name", + "tty": True, + } + self.assertEqual(cnt, expected_cnt) + + +def get_minimal_container(): + return {} + + +def get_minimal_compose(): + return PodmanCompose() + + +def get_minimal_args(): + return argparse.Namespace( + T=None, + cnt_command=None, + entrypoint=None, + env=None, + name="default_name", + rm=None, + service=None, + service_ports=None, + user=None, + volume=None, + workdir=None, + )