1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
Description: Fix issue with ansible.builtin.copy when using libvirt connection plugin
The libvirt connection plugin is unable to resolve "~", leading to files copied
to literal /~/ansible-tmp/, and thus many modules failing.
Author: antonc42
Origin: upstream, https://github.com/ansible-collections/community.libvirt/pull/162
Bug: https://github.com/ansible-collections/community.libvirt/issues/161
Applied-Upstream: not yet
Reviewed-by: Lee Garrett <debian@rocketjump.eu>
Last-Update: 2023-10-20
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- /dev/null
+++ b/ansible_collections/community/libvirt/changelogs/fragments/161_fix_resolve_tilde.yml
@@ -0,0 +1,2 @@
+bugfixes:
+ - libvirt_qemu - fix path resolution of tilde (~) used to represent remote user's homedir
--- a/ansible_collections/community/libvirt/plugins/connection/libvirt_qemu.py
+++ b/ansible_collections/community/libvirt/plugins/connection/libvirt_qemu.py
@@ -46,6 +46,7 @@
import base64
import json
+import re
import shlex
import time
import traceback
@@ -99,6 +100,7 @@
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
self._host = self._play_context.remote_addr
+ self._user_homedir = None
# Windows operates differently from a POSIX connection/shell plugin,
# we need to set various properties to ensure SSH on Windows continues
@@ -147,6 +149,21 @@
display.vvv(u"ESTABLISH {0} CONNECTION".format(self.transport), host=self._host)
self._connected = True
+ @property
+ def user_homedir(self):
+ """ the resolved user homedir on the remote """
+ if self._user_homedir:
+ return self._user_homedir
+ exitcode, stdout, stderr = self.exec_command("/bin/sh -c 'getent passwd $(id -un) | cut -d: -f6'")
+ self._user_homedir = to_text(stdout).strip()
+ return self._user_homedir
+
+ def _resolve_tilde(self, string):
+ """ resolve file paths or commands that begin with '~/' to the remote user's homedir """
+ if re.search(r"~\/", string):
+ return re.sub(r"~\/", self.user_homedir + r"/", string)
+ return string
+
def exec_command(self, cmd, in_data=None, sudoable=True):
""" execute a command on the virtual machine host """
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
@@ -154,6 +171,7 @@
self._display.vvv(u"EXEC {0}".format(cmd), host=self._host)
cmd_args_list = shlex.split(to_native(cmd, errors='surrogate_or_strict'))
+ cmd_args_list = list(map(self._resolve_tilde, cmd_args_list))
if getattr(self._shell, "_IS_WINDOWS", False):
# Become method 'runas' is done in the wrapper that is executed,
@@ -242,6 +260,7 @@
def put_file(self, in_path, out_path):
''' transfer a file from local to domain '''
super(Connection, self).put_file(in_path, out_path)
+ out_path = self._resolve_tilde(out_path)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._host)
if not exists(to_bytes(in_path, errors='surrogate_or_strict')):
@@ -304,6 +323,7 @@
def fetch_file(self, in_path, out_path):
''' fetch a file from domain to local '''
super(Connection, self).fetch_file(in_path, out_path)
+ in_path = self._resolve_tilde(in_path)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._host)
request_handle = {
|