mirror of
https://github.com/containers/podman-compose.git
synced 2025-04-10 18:48:25 +02:00
Allow providing custom in_pod argument as a global compose file variable
Default command line argument `in_pod` was set to True, but this breaks the compose file for users who want to use `--userns` argument. This commit sets default `in_pod` value to None, and later resolves whether to create a pod by checking compose file, as new argument in compose file x-podman is now available. Now it is convenient for users to pass custom `in_pod` value (True or False) as a compose file argument when command line value of `in_pod` is not provided. Signed-off-by: Monika Kairaityte <monika@kibit.lt>
This commit is contained in:
parent
14f39e5b86
commit
360b85bf2d
@ -89,3 +89,23 @@ In addition, podman-compose supports the following podman-specific values for `n
|
||||
|
||||
The options to the network modes are passed to the `--network` option of the `podman create` command
|
||||
as-is.
|
||||
|
||||
|
||||
## Custom pods management
|
||||
|
||||
Podman-compose can have containers in pods. This can be controlled by extension key x-podman in_pod.
|
||||
It allows providing custom value for --in-pod and is especially relevant when --userns has to be set.
|
||||
|
||||
For example, the following docker-compose.yml allows using userns_mode by overriding the default
|
||||
value of --in-pod (unless it was specifically provided by "--in-pod=True" in command line interface).
|
||||
```yml
|
||||
version: "3"
|
||||
services:
|
||||
cont:
|
||||
image: nopush/podman-compose-test
|
||||
userns_mode: keep-id:uid=1000
|
||||
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-p", "8080"]
|
||||
|
||||
x-podman:
|
||||
in_pod: false
|
||||
```
|
||||
|
@ -1741,6 +1741,18 @@ class PodmanCompose:
|
||||
if isinstance(retcode, int):
|
||||
sys.exit(retcode)
|
||||
|
||||
def resolve_in_pod(self, compose):
|
||||
if self.global_args.in_pod_bool is None:
|
||||
extension_dict = compose.get("x-podman", None)
|
||||
if extension_dict is not None:
|
||||
in_pod_value = extension_dict.get("in_pod", None)
|
||||
if in_pod_value is not None:
|
||||
self.global_args.in_pod_bool = in_pod_value
|
||||
else:
|
||||
self.global_args.in_pod_bool = True
|
||||
# otherwise use `in_pod` value provided by command line
|
||||
return self.global_args.in_pod_bool
|
||||
|
||||
def _parse_compose_file(self):
|
||||
args = self.global_args
|
||||
# cmd = args.command
|
||||
@ -1968,6 +1980,8 @@ class PodmanCompose:
|
||||
given_containers = list(container_by_name.values())
|
||||
given_containers.sort(key=lambda c: len(c.get("_deps", None) or []))
|
||||
# log("sorted:", [c["name"] for c in given_containers])
|
||||
|
||||
args.in_pod_bool = self.resolve_in_pod(compose)
|
||||
pods, containers = transform(args, project_name, given_containers)
|
||||
self.pods = pods
|
||||
self.containers = containers
|
||||
@ -2005,12 +2019,22 @@ class PodmanCompose:
|
||||
for cmd_parser in cmd._parse_args: # pylint: disable=protected-access
|
||||
cmd_parser(subparser)
|
||||
self.global_args = parser.parse_args()
|
||||
if self.global_args.in_pod.lower() not in ('', 'true', '1', 'false', '0'):
|
||||
if self.global_args.in_pod is not None and self.global_args.in_pod.lower() not in (
|
||||
'',
|
||||
'true',
|
||||
'1',
|
||||
'false',
|
||||
'0',
|
||||
):
|
||||
raise ValueError(
|
||||
f'Invalid --in-pod value: \'{self.global_args.in_pod}\'. '
|
||||
'It must be set to either of: empty value, true, 1, false, 0'
|
||||
)
|
||||
self.global_args.in_pod_bool = self.global_args.in_pod.lower() in ('', 'true', '1')
|
||||
|
||||
if self.global_args.in_pod == '' or self.global_args.in_pod is None:
|
||||
self.global_args.in_pod_bool = None
|
||||
else:
|
||||
self.global_args.in_pod_bool = self.global_args.in_pod.lower() in ('true', '1')
|
||||
|
||||
if self.global_args.version:
|
||||
self.global_args.command = "version"
|
||||
@ -2029,7 +2053,7 @@ class PodmanCompose:
|
||||
help="pod creation",
|
||||
metavar="in_pod",
|
||||
type=str,
|
||||
default="true",
|
||||
default=None,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pod-args",
|
||||
|
9
tests/in_pod/custom_x-podman_false/docker-compose.yml
Normal file
9
tests/in_pod/custom_x-podman_false/docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: "3"
|
||||
services:
|
||||
cont:
|
||||
image: nopush/podman-compose-test
|
||||
userns_mode: keep-id:uid=1000
|
||||
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-p", "8080"]
|
||||
|
||||
x-podman:
|
||||
in_pod: false
|
@ -0,0 +1,6 @@
|
||||
version: "3"
|
||||
services:
|
||||
cont:
|
||||
image: nopush/podman-compose-test
|
||||
userns_mode: keep-id:uid=1000
|
||||
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-p", "8080"]
|
9
tests/in_pod/custom_x-podman_true/docker-compose.yml
Normal file
9
tests/in_pod/custom_x-podman_true/docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: "3"
|
||||
services:
|
||||
cont:
|
||||
image: nopush/podman-compose-test
|
||||
userns_mode: keep-id:uid=1000
|
||||
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-p", "8080"]
|
||||
|
||||
x-podman:
|
||||
in_pod: true
|
442
tests/test_podman_compose_in_pod.py
Normal file
442
tests/test_podman_compose_in_pod.py
Normal file
@ -0,0 +1,442 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
import os
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from .test_utils import RunSubprocessMixin
|
||||
|
||||
|
||||
def base_path():
|
||||
"""Returns the base path for the project"""
|
||||
return Path(__file__).parent.parent
|
||||
|
||||
|
||||
def test_path():
|
||||
"""Returns the path to the tests directory"""
|
||||
return os.path.join(base_path(), "tests")
|
||||
|
||||
|
||||
def podman_compose_path():
|
||||
"""Returns the path to the podman compose script"""
|
||||
return os.path.join(base_path(), "podman_compose.py")
|
||||
|
||||
|
||||
# If a compose file has userns_mode set, setting in_pod to True, results in error.
|
||||
# Default in_pod setting is True, unless compose file provides otherwise.
|
||||
# Compose file provides custom in_pod option, which can be overridden by command line in_pod option.
|
||||
# Test all combinations of command line argument in_pod and compose file argument in_pod.
|
||||
class TestPodmanComposeInPod(unittest.TestCase, RunSubprocessMixin):
|
||||
# compose file provides x-podman in_pod=false
|
||||
def test_x_podman_in_pod_false_command_line_in_pod_not_exists(self):
|
||||
"""
|
||||
Test that podman-compose will not create a pod, when x-podman in_pod=false and command line
|
||||
does not provide this option
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_false", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
down_cmd = [
|
||||
"python3",
|
||||
podman_compose_path(),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_false", "docker-compose.yml")
|
||||
),
|
||||
"down",
|
||||
]
|
||||
|
||||
try:
|
||||
self.run_subprocess_assert_returncode(command_up)
|
||||
|
||||
finally:
|
||||
self.run_subprocess_assert_returncode(down_cmd)
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_false"]
|
||||
# throws an error, can not actually find this pod because it was not created
|
||||
self.run_subprocess_assert_returncode(command_rm_pod, expected_returncode=1)
|
||||
|
||||
def test_x_podman_in_pod_false_command_line_in_pod_true(self):
|
||||
"""
|
||||
Test that podman-compose does not allow pod creating even with command line in_pod=True
|
||||
when --userns and --pod are set together: throws an error
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
# FIXME: creates a pod anyway, although it should not
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=True",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_false", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
try:
|
||||
out, err = self.run_subprocess_assert_returncode(command_up)
|
||||
self.assertEqual(b"Error: --userns and --pod cannot be set together" in err, True)
|
||||
|
||||
finally:
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_false"]
|
||||
# should throw an error of not being able to find this pod (because it should not have
|
||||
# been created) and have expected_returncode=1 (see FIXME above)
|
||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||
|
||||
def test_x_podman_in_pod_false_command_line_in_pod_false(self):
|
||||
"""
|
||||
Test that podman-compose will not create a pod as command line sets in_pod=False
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=False",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_false", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
down_cmd = [
|
||||
"python3",
|
||||
podman_compose_path(),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_false", "docker-compose.yml")
|
||||
),
|
||||
"down",
|
||||
]
|
||||
|
||||
try:
|
||||
self.run_subprocess_assert_returncode(command_up)
|
||||
|
||||
finally:
|
||||
self.run_subprocess_assert_returncode(down_cmd)
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_false"]
|
||||
# can not actually find this pod because it was not created
|
||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||
|
||||
def test_x_podman_in_pod_false_command_line_in_pod_empty_string(self):
|
||||
"""
|
||||
Test that podman-compose will not create a pod, when x-podman in_pod=false and command line
|
||||
command line in_pod=""
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_false", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
down_cmd = [
|
||||
"python3",
|
||||
podman_compose_path(),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_false", "docker-compose.yml")
|
||||
),
|
||||
"down",
|
||||
]
|
||||
|
||||
try:
|
||||
self.run_subprocess_assert_returncode(command_up)
|
||||
|
||||
finally:
|
||||
self.run_subprocess_assert_returncode(down_cmd)
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_false"]
|
||||
# can not actually find this pod because it was not created
|
||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||
|
||||
# compose file provides x-podman in_pod=true
|
||||
def test_x_podman_in_pod_true_command_line_in_pod_not_exists(self):
|
||||
"""
|
||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||
together even when x-podman in_pod=true: throws an error
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
# FIXME: creates a pod anyway, although it should not
|
||||
# Container is not created, so command 'down' is not needed
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_true", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
try:
|
||||
out, err = self.run_subprocess_assert_returncode(command_up)
|
||||
self.assertEqual(b"Error: --userns and --pod cannot be set together" in err, True)
|
||||
|
||||
finally:
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_true"]
|
||||
# should throw an error of not being able to find this pod (it should not have been
|
||||
# created) and have expected_returncode=1 (see FIXME above)
|
||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||
|
||||
def test_x_podman_in_pod_true_command_line_in_pod_true(self):
|
||||
"""
|
||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||
together even when x-podman in_pod=true and and command line in_pod=True: throws an error
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
# FIXME: creates a pod anyway, although it should not
|
||||
# Container is not created, so command 'down' is not needed
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=True",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_true", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
try:
|
||||
out, err = self.run_subprocess_assert_returncode(command_up)
|
||||
self.assertEqual(b"Error: --userns and --pod cannot be set together" in err, True)
|
||||
|
||||
finally:
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_true"]
|
||||
# should throw an error of not being able to find this pod (because it should not have
|
||||
# been created) and have expected_returncode=1 (see FIXME above)
|
||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||
|
||||
def test_x_podman_in_pod_true_command_line_in_pod_false(self):
|
||||
"""
|
||||
Test that podman-compose will not create a pod as command line sets in_pod=False
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=False",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_true", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
down_cmd = [
|
||||
"python3",
|
||||
podman_compose_path(),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_true", "docker-compose.yml")
|
||||
),
|
||||
"down",
|
||||
]
|
||||
|
||||
try:
|
||||
self.run_subprocess_assert_returncode(command_up)
|
||||
|
||||
finally:
|
||||
self.run_subprocess_assert_returncode(down_cmd)
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_false"]
|
||||
# can not actually find this pod because it was not created
|
||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||
|
||||
def test_x_podman_in_pod_true_command_line_in_pod_empty_string(self):
|
||||
"""
|
||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||
together even when x-podman in_pod=true and command line in_pod="": throws an error
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
# FIXME: creates a pod anyway, although it should not
|
||||
# Container is not created, so command 'down' is not needed
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath("tests", "in_pod", "custom_x-podman_true", "docker-compose.yml")
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
try:
|
||||
out, err = self.run_subprocess_assert_returncode(command_up)
|
||||
self.assertEqual(b"Error: --userns and --pod cannot be set together" in err, True)
|
||||
|
||||
finally:
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_true"]
|
||||
# should throw an error of not being able to find this pod (because it should not have
|
||||
# been created) and have expected_returncode=1 (see FIXME above)
|
||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||
|
||||
# compose file does not provide x-podman in_pod
|
||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_not_exists(self):
|
||||
"""
|
||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||
together: throws an error
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
# FIXME: creates a pod anyway, although it should not
|
||||
# Container is not created, so command 'down' is not needed
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath(
|
||||
"tests", "in_pod", "custom_x-podman_not_exists", "docker-compose.yml"
|
||||
)
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
try:
|
||||
out, err = self.run_subprocess_assert_returncode(command_up)
|
||||
self.assertEqual(b"Error: --userns and --pod cannot be set together" in err, True)
|
||||
|
||||
finally:
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_not_exists"]
|
||||
# should throw an error of not being able to find this pod (it should not have been
|
||||
# created) and have expected_returncode=1 (see FIXME above)
|
||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||
|
||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_true(self):
|
||||
"""
|
||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||
together even when x-podman in_pod=true: throws an error
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
# FIXME: creates a pod anyway, although it should not
|
||||
# Container was not created, so command 'down' is not needed
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=True",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath(
|
||||
"tests", "in_pod", "custom_x-podman_not_exists", "docker-compose.yml"
|
||||
)
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
try:
|
||||
out, err = self.run_subprocess_assert_returncode(command_up)
|
||||
self.assertEqual(b"Error: --userns and --pod cannot be set together" in err, True)
|
||||
|
||||
finally:
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_not_exists"]
|
||||
# should throw an error of not being able to find this pod (because it should not have
|
||||
# been created) and have expected_returncode=1 (see FIXME above)
|
||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
||||
|
||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_false(self):
|
||||
"""
|
||||
Test that podman-compose will not create a pod as command line sets in_pod=False
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=False",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath(
|
||||
"tests", "in_pod", "custom_x-podman_not_exists", "docker-compose.yml"
|
||||
)
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
down_cmd = [
|
||||
"python3",
|
||||
podman_compose_path(),
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath(
|
||||
"tests", "in_pod", "custom_x-podman_not_exists", "docker-compose.yml"
|
||||
)
|
||||
),
|
||||
"down",
|
||||
]
|
||||
|
||||
try:
|
||||
self.run_subprocess_assert_returncode(command_up)
|
||||
|
||||
finally:
|
||||
self.run_subprocess_assert_returncode(down_cmd)
|
||||
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_not_exists"]
|
||||
# can not actually find this pod because it was not created
|
||||
self.run_subprocess_assert_returncode(command_rm_pod, 1)
|
||||
|
||||
def test_x_podman_in_pod_not_exists_command_line_in_pod_empty_string(self):
|
||||
"""
|
||||
Test that podman-compose does not allow pod creating when --userns and --pod are set
|
||||
together: throws an error
|
||||
"""
|
||||
main_path = Path(__file__).parent.parent
|
||||
|
||||
# FIXME: creates a pod anyway, although it should not
|
||||
# Container was not created, so command 'down' is not needed
|
||||
command_up = [
|
||||
"python3",
|
||||
str(main_path.joinpath("podman_compose.py")),
|
||||
"--in-pod=",
|
||||
"-f",
|
||||
str(
|
||||
main_path.joinpath(
|
||||
"tests", "in_pod", "custom_x-podman_not_exists", "docker-compose.yml"
|
||||
)
|
||||
),
|
||||
"up",
|
||||
"-d",
|
||||
]
|
||||
|
||||
try:
|
||||
out, err = self.run_subprocess_assert_returncode(command_up)
|
||||
self.assertEqual(b"Error: --userns and --pod cannot be set together" in err, True)
|
||||
|
||||
finally:
|
||||
command_rm_pod = ["podman", "pod", "rm", "pod_custom_x-podman_not_exists"]
|
||||
# should throw an error of not being able to find this pod (because it should not have
|
||||
# been created) and have expected_returncode=1 (see FIXME above)
|
||||
self.run_subprocess_assert_returncode(command_rm_pod)
|
Loading…
Reference in New Issue
Block a user