Fix failed mounts in podman connector and handle errors (#57741)
Like it's described in issue #57740 ansible podman fails to run because of failed mount of rootless container.
This commit is contained in:
parent
0d2ffdd5a6
commit
7910361b52
2 changed files with 39 additions and 16 deletions
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- ansible-podman connection plugin - Fix case when mount of podman container fails and files can't be copied to/from container. Also add error handling in case of failed podman commands. (https://github.com/ansible/ansible/issues/57740)
|
|
@ -14,6 +14,7 @@ import shlex
|
|||
import shutil
|
||||
import subprocess
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.module_utils._text import to_bytes, to_native
|
||||
from ansible.plugins.connection import ConnectionBase, ensure_connect
|
||||
from ansible.utils.display import Display
|
||||
|
@ -68,7 +69,7 @@ class Connection(ConnectionBase):
|
|||
self._mount_point = None
|
||||
self.user = self._play_context.remote_user
|
||||
|
||||
def _podman(self, cmd, cmd_args=None, in_data=None):
|
||||
def _podman(self, cmd, cmd_args=None, in_data=None, use_container_id=True):
|
||||
"""
|
||||
run podman executable
|
||||
|
||||
|
@ -77,7 +78,9 @@ class Connection(ConnectionBase):
|
|||
:param in_data: data passed to podman's stdin
|
||||
:return: return code, stdout, stderr
|
||||
"""
|
||||
local_cmd = ['podman', cmd, self._container_id]
|
||||
local_cmd = ['podman', cmd]
|
||||
if use_container_id:
|
||||
local_cmd.append(self._container_id)
|
||||
if cmd_args:
|
||||
local_cmd += cmd_args
|
||||
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
|
||||
|
@ -87,6 +90,9 @@ class Connection(ConnectionBase):
|
|||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
stdout, stderr = p.communicate(input=in_data)
|
||||
display.vvvvv("STDOUT %s" % stdout)
|
||||
display.vvvvv("STDERR %s" % stderr)
|
||||
display.vvvvv("RC CODE %s" % p.returncode)
|
||||
stdout = to_bytes(stdout, errors='surrogate_or_strict')
|
||||
stderr = to_bytes(stderr, errors='surrogate_or_strict')
|
||||
return p.returncode, stdout, stderr
|
||||
|
@ -98,8 +104,11 @@ class Connection(ConnectionBase):
|
|||
"""
|
||||
super(Connection, self)._connect()
|
||||
rc, self._mount_point, stderr = self._podman("mount")
|
||||
self._mount_point = self._mount_point.strip()
|
||||
display.vvvvv("MOUNTPOINT %s RC %s STDERR %r" % (self._mount_point, rc, stderr))
|
||||
if rc != 0:
|
||||
display.v("Failed to mount container %s: %s" % (self._container_id, stderr.strip()))
|
||||
else:
|
||||
self._mount_point = self._mount_point.strip()
|
||||
display.vvvvv("MOUNTPOINT %s RC %s STDERR %r" % (self._mount_point, rc, stderr))
|
||||
self._connected = True
|
||||
|
||||
@ensure_connect
|
||||
|
@ -121,23 +130,35 @@ class Connection(ConnectionBase):
|
|||
""" Place a local file located in 'in_path' inside container at 'out_path' """
|
||||
super(Connection, self).put_file(in_path, out_path)
|
||||
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._container_id)
|
||||
|
||||
real_out_path = self._mount_point + to_bytes(out_path, errors='surrogate_or_strict')
|
||||
shutil.copyfile(
|
||||
to_bytes(in_path, errors='surrogate_or_strict'),
|
||||
to_bytes(real_out_path, errors='surrogate_or_strict')
|
||||
)
|
||||
if not self._mount_point:
|
||||
rc, stdout, stderr = self._podman(
|
||||
"cp", [in_path, self._container_id + ":" + out_path], use_container_id=False)
|
||||
if rc != 0:
|
||||
raise AnsibleError("Failed to copy file from %s to %s in container %s\n%s" % (
|
||||
in_path, out_path, self._container_id, stderr))
|
||||
else:
|
||||
real_out_path = self._mount_point + to_bytes(out_path, errors='surrogate_or_strict')
|
||||
shutil.copyfile(
|
||||
to_bytes(in_path, errors='surrogate_or_strict'),
|
||||
to_bytes(real_out_path, errors='surrogate_or_strict')
|
||||
)
|
||||
|
||||
def fetch_file(self, in_path, out_path):
|
||||
""" obtain file specified via 'in_path' from the container and place it at 'out_path' """
|
||||
super(Connection, self).fetch_file(in_path, out_path)
|
||||
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._container_id)
|
||||
|
||||
real_in_path = self._mount_point + to_bytes(in_path, errors='surrogate_or_strict')
|
||||
shutil.copyfile(
|
||||
to_bytes(real_in_path, errors='surrogate_or_strict'),
|
||||
to_bytes(out_path, errors='surrogate_or_strict')
|
||||
)
|
||||
if not self._mount_point:
|
||||
rc, stdout, stderr = self._podman(
|
||||
"cp", [self._container_id + ":" + in_path, out_path], use_container_id=False)
|
||||
if rc != 0:
|
||||
raise AnsibleError("Failed to fetch file from %s to %s from container %s\n%s" % (
|
||||
in_path, out_path, self._container_id, stderr))
|
||||
else:
|
||||
real_in_path = self._mount_point + to_bytes(in_path, errors='surrogate_or_strict')
|
||||
shutil.copyfile(
|
||||
to_bytes(real_in_path, errors='surrogate_or_strict'),
|
||||
to_bytes(out_path, errors='surrogate_or_strict')
|
||||
)
|
||||
|
||||
def close(self):
|
||||
""" unmount container's filesystem """
|
||||
|
|
Loading…
Reference in a new issue