Skip to content

Commit 03d2c38

Browse files
committed
fix async sudo askpass helper setup
1 parent 6163f76 commit 03d2c38

2 files changed

Lines changed: 47 additions & 3 deletions

File tree

src/pyinfra/connectors/util.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,16 +353,28 @@ def extract_control_arguments(arguments: "ConnectorArguments") -> "ConnectorArgu
353353
def _ensure_sudo_askpass_set_for_host(host: "Host"):
354354
if host.connector_data.get("sudo_askpass_path"):
355355
return
356-
_, output = host.run_shell_command(
356+
357+
status, output = host.run_shell_command(
357358
SUDO_ASKPASS_COMMAND.format(host.get_temp_dir_config(), SUDO_ASKPASS_ENV_VAR)
358359
)
360+
361+
if status is False or not output.stdout_lines or not output.stdout_lines[0]:
362+
raise RuntimeError("Failed to create sudo askpass helper")
363+
359364
host.connector_data["sudo_askpass_path"] = shlex.quote(output.stdout_lines[0])
360365

361366

362367
async def _ensure_sudo_askpass_set_for_host_async(host: "Host") -> None:
363368
if host.connector_data.get("sudo_askpass_path"):
364369
return
365-
_, output = await host.run_shell_command_async(SUDO_ASKPASS_COMMAND)
370+
371+
status, output = await host.run_shell_command_async(
372+
SUDO_ASKPASS_COMMAND.format(host.get_temp_dir_config(), SUDO_ASKPASS_ENV_VAR)
373+
)
374+
375+
if status is False or not output.stdout_lines or not output.stdout_lines[0]:
376+
raise RuntimeError("Failed to create sudo askpass helper")
377+
366378
host.connector_data["sudo_askpass_path"] = shlex.quote(output.stdout_lines[0])
367379

368380

tests/test_connectors/test_util.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22

33
from unittest import TestCase
44

5+
import asyncio
6+
57
from pyinfra.api import Config, State
6-
from pyinfra.connectors.util import make_unix_command, make_unix_command_for_host
8+
from pyinfra.connectors.util import (
9+
CommandOutput,
10+
OutputLine,
11+
async_make_unix_command_for_host,
12+
make_unix_command,
13+
make_unix_command_for_host,
14+
)
715

816
from ..util import make_inventory
917

@@ -100,6 +108,30 @@ def test_mixed_command(self):
100108
"&& echo hi'\"'\"''" # command bit
101109
)
102110

111+
def test_async_sudo_password_sets_askpass(self):
112+
state = State(make_inventory(), Config())
113+
host = state.inventory.get_host("somehost")
114+
115+
async def fake_run_shell_command_async(*_args, **_kwargs):
116+
return True, CommandOutput([OutputLine("stdout", "/tmp/pyinfra-askpass")])
117+
118+
host.run_shell_command_async = fake_run_shell_command_async
119+
120+
command = asyncio.run(
121+
async_make_unix_command_for_host(
122+
state,
123+
host,
124+
"uptime",
125+
_sudo=True,
126+
_sudo_password="password",
127+
)
128+
)
129+
130+
raw = command.get_raw_value()
131+
assert "SUDO_ASKPASS=/tmp/pyinfra-askpass" in raw
132+
assert "PYINFRA_SUDO_PASSWORD=password" in raw
133+
assert "sudo -H -A -k" in raw
134+
103135
def test_command_exists_su_config_only(self):
104136
"""
105137
This tests covers a bug that appeared when `make_unix_command` is called

0 commit comments

Comments
 (0)