diff options
author | Matt Martz <matt@sivel.net> | 2022-03-09 15:59:29 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-09 15:59:29 -0600 |
commit | 7cb581ed2cb1d4591d094df37a40c9155ea446da (patch) | |
tree | 67899ac51fd64f64e44a09b746995743727ba695 | |
parent | 1ba3ead0a02d982563a5108f837eaadb11bd6018 (diff) | |
download | ansible-7cb581ed2cb1d4591d094df37a40c9155ea446da.tar.gz |
Support podman-remote in ansible-test (#75753)
-rw-r--r-- | changelogs/fragments/ansible-test-podman-remote.yaml | 3 | ||||
-rw-r--r-- | test/lib/ansible_test/_internal/containers.py | 10 | ||||
-rw-r--r-- | test/lib/ansible_test/_internal/docker_util.py | 77 | ||||
-rw-r--r-- | test/lib/ansible_test/_internal/util.py | 13 |
4 files changed, 84 insertions, 19 deletions
diff --git a/changelogs/fragments/ansible-test-podman-remote.yaml b/changelogs/fragments/ansible-test-podman-remote.yaml new file mode 100644 index 0000000000..7eb38e110e --- /dev/null +++ b/changelogs/fragments/ansible-test-podman-remote.yaml @@ -0,0 +1,3 @@ +minor_changes: +- ansible-test - Add support for running container tests with ``podman remote`` + (https://github.com/ansible/ansible/pull/75753) diff --git a/test/lib/ansible_test/_internal/containers.py b/test/lib/ansible_test/_internal/containers.py index 5f84890010..5e29c6ac05 100644 --- a/test/lib/ansible_test/_internal/containers.py +++ b/test/lib/ansible_test/_internal/containers.py @@ -15,7 +15,6 @@ from .util import ( ApplicationError, SubprocessError, display, - get_host_ip, sanitize_host_name, ) @@ -43,6 +42,7 @@ from .docker_util import ( docker_start, get_docker_container_id, get_docker_host_ip, + get_podman_host_ip, require_docker, ) @@ -350,8 +350,12 @@ def create_container_database(args): # type: (EnvironmentConfig) -> ContainerDa for name, container in support_containers.items(): if container.details.published_ports: + if require_docker().command == 'podman': + host_ip_func = get_podman_host_ip + else: + host_ip_func = get_docker_host_ip published_access = ContainerAccess( - host_ip=get_docker_host_ip(), + host_ip=host_ip_func(), names=container.aliases, ports=None, forwards=dict((port, published_port) for port, published_port in container.details.published_ports.items()), @@ -370,7 +374,7 @@ def create_container_database(args): # type: (EnvironmentConfig) -> ContainerDa elif require_docker().command == 'podman': # published ports for rootless podman containers should be accessible from the host's IP container_access = ContainerAccess( - host_ip=get_host_ip(), + host_ip=get_podman_host_ip(), names=container.aliases, ports=None, forwards=dict((port, published_port) for port, published_port in container.details.published_ports.items()), diff --git a/test/lib/ansible_test/_internal/docker_util.py b/test/lib/ansible_test/_internal/docker_util.py index 0934b892c0..1e10f5ff58 100644 --- a/test/lib/ansible_test/_internal/docker_util.py +++ b/test/lib/ansible_test/_internal/docker_util.py @@ -122,6 +122,75 @@ def get_docker_hostname(): # type: () -> str @cache +def get_podman_host_ip(): # type: () -> str + """Return the IP of the Podman host.""" + podman_host_ip = socket.gethostbyname(get_podman_hostname()) + + display.info('Detected Podman host IP: %s' % podman_host_ip, verbosity=1) + + return podman_host_ip + + +@cache +def get_podman_default_hostname(): # type: () -> str + """Return the default hostname of the Podman service. + + --format was added in podman 3.3.0, this functionality depends on it's availability + """ + try: + stdout = raw_command(['podman', 'system', 'connection', 'list', '--format=json'], capture=True)[0] + except SubprocessError: + stdout = '[]' + + connections = json.loads(stdout) + + for connection in connections: + # A trailing indicates the default + if connection['Name'][-1] == '*': + hostname = connection['URI'] + break + else: + hostname = None + + return hostname + + +@cache +def _get_podman_remote(): # type: () -> t.Optional[str] + # URL value resolution precedence: + # - command line value + # - environment variable CONTAINER_HOST + # - containers.conf + # - unix://run/podman/podman.sock + hostname = None + + podman_host = os.environ.get('CONTAINER_HOST') + if not podman_host: + podman_host = get_podman_default_hostname() + + if podman_host and podman_host.startswith('ssh://'): + try: + hostname = urllib.parse.urlparse(podman_host).hostname + except ValueError: + display.warning('Could not parse podman URI "%s"' % podman_host) + else: + display.info('Detected Podman remote: %s' % hostname, verbosity=1) + return hostname + + +@cache +def get_podman_hostname(): # type: () -> str + """Return the hostname of the Podman service.""" + hostname = _get_podman_remote() + + if not hostname: + hostname = 'localhost' + display.info('Assuming Podman is available on localhost.', verbosity=1) + + return hostname + + +@cache def get_docker_container_id(): # type: () -> t.Optional[str] """Return the current container ID if running in a container, otherwise return None.""" path = '/proc/self/cpuset' @@ -478,12 +547,14 @@ def docker_command( ): # type: (...) -> t.Tuple[t.Optional[str], t.Optional[str]] """Run the specified docker command.""" env = docker_environment() - command = require_docker().command - return run_command(args, [command] + cmd, env=env, capture=capture, stdin=stdin, stdout=stdout, always=always, data=data) + command = [require_docker().command] + if command[0] == 'podman' and _get_podman_remote(): + command.append('--remote') + return run_command(args, command + cmd, env=env, capture=capture, stdin=stdin, stdout=stdout, always=always, data=data) def docker_environment(): # type: () -> t.Dict[str, str] """Return a dictionary of docker related environment variables found in the current environment.""" env = common_environment() - env.update(dict((key, os.environ[key]) for key in os.environ if key.startswith('DOCKER_'))) + env.update(dict((key, os.environ[key]) for key in os.environ if key.startswith('DOCKER_') or key.startswith('CONTAINER_'))) return env diff --git a/test/lib/ansible_test/_internal/util.py b/test/lib/ansible_test/_internal/util.py index 8d1b7eb498..0ad78882de 100644 --- a/test/lib/ansible_test/_internal/util.py +++ b/test/lib/ansible_test/_internal/util.py @@ -11,7 +11,6 @@ import pkgutil import random import re import shutil -import socket import stat import string import subprocess @@ -782,18 +781,6 @@ def sanitize_host_name(name): return re.sub('[^A-Za-z0-9]+', '-', name)[:63].strip('-') -@cache -def get_host_ip(): - """Return the host's IP address.""" - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: - sock.connect(('10.255.255.255', 22)) - host_ip = get_host_ip.ip = sock.getsockname()[0] - - display.info('Detected host IP: %s' % host_ip, verbosity=1) - - return host_ip - - def get_generic_type(base_type, generic_base_type): # type: (t.Type, t.Type[TType]) -> t.Optional[t.Type[TType]] """Return the generic type arg derived from the generic_base_type type that is associated with the base_type type, if any, otherwise return None.""" # noinspection PyUnresolvedReferences |