mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-02-04 07:51:50 +00:00
[PR #11308/4b67afc2 backport][stable-12] Add option for wsl_shell_type, protect wsl.exe arguments if SSH shell is Powershell (#11433)
Add option for wsl_shell_type, protect wsl.exe arguments if SSH shell is Powershell (#11308)
* feat(wsl): add option for wsl_shell_type, protect wsl arguments if SSH shell is Powershell
* docs(wsl): add changelog fragment
* docs(wsl): fix changelog fragment syntax, add issue link
* feat(wsl): improve new option documentation
* refactor(wsl): put integrasion test flag into a variable for convenience
* feat(wsl): rename option to wsl_remote_ssh_shell_type
* feat(wsl): escape "%" if shell is cmd, raise AnsibleError if powershell
* test(wsl): fix unit tests for wsl
- remove redundant check - moved to a separate function
- fix check for cmd escaping of "%"
- fix formatting / whitespace
* test(wsl): fix expected error message
* test(wsl): fix test - position of stop-parsing token changed
---------
(cherry picked from commit 4b67afc2b0)
Co-authored-by: fizmat <fizmat.r66@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
68b2385efd
commit
5b571fd53f
3 changed files with 45 additions and 3 deletions
3
changelogs/fragments/11308-wsl-shell-type.yml
Normal file
3
changelogs/fragments/11308-wsl-shell-type.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
minor_changes:
|
||||
- wsl connection plugin - add option ``wsl_remote_ssh_shell_type``. Support PowerShell in addition to cmd as the Windows
|
||||
shell (https://github.com/ansible-collections/community.general/issues/11307, https://github.com/ansible-collections/community.general/pull/11308).
|
||||
|
|
@ -231,6 +231,18 @@ options:
|
|||
required: true
|
||||
vars:
|
||||
- name: wsl_distribution
|
||||
wsl_remote_ssh_shell_type:
|
||||
description:
|
||||
- The shell type expected in the SSH session (not inside the WSL session).
|
||||
- See also C(ansible_shell_type).
|
||||
type: string
|
||||
choices:
|
||||
- cmd
|
||||
- powershell
|
||||
default: cmd
|
||||
vars:
|
||||
- name: wsl_remote_ssh_shell_type
|
||||
version_added: 12.2.0
|
||||
wsl_user:
|
||||
description:
|
||||
- WSL distribution user.
|
||||
|
|
@ -578,18 +590,32 @@ class Connection(ConnectionBase):
|
|||
wsl_distribution = self.get_option("wsl_distribution")
|
||||
become = self.get_option("become")
|
||||
become_user = self.get_option("become_user")
|
||||
wsl_remote_ssh_shell_type = self.get_option("wsl_remote_ssh_shell_type")
|
||||
is_integration_test = os.getenv("_ANSIBLE_TEST_WSL_CONNECTION_PLUGIN_WAERI5TEPHEESHA2FAE8")
|
||||
if "%" in cmd:
|
||||
if wsl_remote_ssh_shell_type == "powershell":
|
||||
# there is no universal way to escape '%' here
|
||||
# if this is raised, add a workaround to allow the specific situation (if possible)
|
||||
raise AnsibleError("The command contains '%', cannot safely escape it for Powershell")
|
||||
else:
|
||||
cmd = cmd.replace("%", "^%")
|
||||
if become and become_user:
|
||||
wsl_user = become_user
|
||||
else:
|
||||
wsl_user = self.get_option("wsl_user")
|
||||
args = ["wsl.exe", "--distribution", wsl_distribution]
|
||||
args = ["wsl.exe"]
|
||||
if wsl_remote_ssh_shell_type == "powershell" and not is_integration_test:
|
||||
# Powershell stop-parsing token, treat the rest as arguments to the native command wsl.exe
|
||||
args.append("--%")
|
||||
args.extend(["--distribution", wsl_distribution])
|
||||
if wsl_user:
|
||||
args.extend(["--user", wsl_user])
|
||||
args.extend(["--"])
|
||||
args.extend(shlex.split(cmd))
|
||||
if os.getenv("_ANSIBLE_TEST_WSL_CONNECTION_PLUGIN_WAERI5TEPHEESHA2FAE8"):
|
||||
if is_integration_test:
|
||||
return shlex.join(args)
|
||||
return list2cmdline(args) # see https://github.com/python/cpython/blob/3.11/Lib/subprocess.py#L576
|
||||
else:
|
||||
return list2cmdline(args) # see https://github.com/python/cpython/blob/3.11/Lib/subprocess.py#L576
|
||||
|
||||
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
||||
"""run a command on inside a WSL distribution"""
|
||||
|
|
|
|||
|
|
@ -210,6 +210,19 @@ def test_build_wsl_command(connection):
|
|||
assert cmd == 'wsl.exe --distribution test --user test-become-user -- /bin/sh -c "ls -la"'
|
||||
|
||||
|
||||
def test_build_wsl_command_powershell(connection):
|
||||
"""Test wsl command building for powershell and cmd remote ssh shell"""
|
||||
cmd = connection._build_wsl_command('/bin/sh -c "ls -la %PATH%"')
|
||||
assert cmd == 'wsl.exe --distribution test -- /bin/sh -c "ls -la ^%PATH^%"'
|
||||
|
||||
connection.set_option("wsl_remote_ssh_shell_type", "powershell")
|
||||
cmd = connection._build_wsl_command('/bin/sh -c "ls -la"')
|
||||
assert cmd == 'wsl.exe --% --distribution test -- /bin/sh -c "ls -la"'
|
||||
|
||||
with pytest.raises(AnsibleError, match="The command contains '%', cannot safely escape it for Powershell"):
|
||||
connection._build_wsl_command('/bin/sh -c "ls -la %PATH%"')
|
||||
|
||||
|
||||
@patch("paramiko.SSHClient")
|
||||
def test_exec_command_success(mock_ssh, connection):
|
||||
"""Test successful command execution"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue