mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-02-04 07:51:50 +00:00
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 Co-authored-by: Felix Fontein <felix@fontein.de> * feat(wsl): improve new option documentation Co-authored-by: Felix Fontein <felix@fontein.de> * 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 Co-authored-by: Felix Fontein <felix@fontein.de> --------- Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
4b0aeede69
commit
4b67afc2b0
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
|
required: true
|
||||||
vars:
|
vars:
|
||||||
- name: wsl_distribution
|
- 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:
|
wsl_user:
|
||||||
description:
|
description:
|
||||||
- WSL distribution user.
|
- WSL distribution user.
|
||||||
|
|
@ -578,18 +590,32 @@ class Connection(ConnectionBase):
|
||||||
wsl_distribution = self.get_option("wsl_distribution")
|
wsl_distribution = self.get_option("wsl_distribution")
|
||||||
become = self.get_option("become")
|
become = self.get_option("become")
|
||||||
become_user = self.get_option("become_user")
|
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:
|
if become and become_user:
|
||||||
wsl_user = become_user
|
wsl_user = become_user
|
||||||
else:
|
else:
|
||||||
wsl_user = self.get_option("wsl_user")
|
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:
|
if wsl_user:
|
||||||
args.extend(["--user", wsl_user])
|
args.extend(["--user", wsl_user])
|
||||||
args.extend(["--"])
|
args.extend(["--"])
|
||||||
args.extend(shlex.split(cmd))
|
args.extend(shlex.split(cmd))
|
||||||
if os.getenv("_ANSIBLE_TEST_WSL_CONNECTION_PLUGIN_WAERI5TEPHEESHA2FAE8"):
|
if is_integration_test:
|
||||||
return shlex.join(args)
|
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]:
|
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"""
|
"""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"'
|
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")
|
@patch("paramiko.SSHClient")
|
||||||
def test_exec_command_success(mock_ssh, connection):
|
def test_exec_command_success(mock_ssh, connection):
|
||||||
"""Test successful command execution"""
|
"""Test successful command execution"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue