You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/api/connectors.md
+55-1Lines changed: 55 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -56,7 +56,7 @@ class MyConnector(BaseConnector):
56
56
@staticmethod
57
57
defmake_names_data(_=None):
58
58
...# see above
59
-
59
+
60
60
defrun_shell_command(
61
61
self,
62
62
command: StringCommand,
@@ -191,6 +191,60 @@ screen.
191
191
`disconnect` can be used after all operations complete to clean up any connection/s remaining to the hosts being managed.
192
192
193
193
194
+
## Implementing `run_shell_command`
195
+
196
+
When implementing `run_shell_command`, connectors should use pyinfra's command wrapping utilities rather than manually constructing commands. The `make_unix_command_for_host()` function from `pyinfra.connectors.util` handles shell wrapping, sudo elevation, environment variables, working directory changes, command retries and shell executable selection.
197
+
198
+
Its worth being aware that when passing `arguments` to `make_unix_command_for_host()`, connector control parameters must be filtered out. These parameters (`_success_exit_codes`, `_timeout`, `_get_pty`, `_stdin`) are defined in `pyinfra.api.arguments.ConnectorArguments` and are meant for the connector's internal logic after command generation, not for command construction itself.
199
+
200
+
The recommended approach is to use `extract_control_arguments()` from `pyinfra.connectors.util` which handles this filtering for you:
201
+
202
+
```py
203
+
from pyinfra.connectors.util import extract_control_arguments, make_unix_command_for_host
204
+
205
+
classMyConnector(BaseConnector):
206
+
handles_execution =True
207
+
208
+
defrun_shell_command(
209
+
self,
210
+
command: StringCommand,
211
+
print_output: bool=False,
212
+
print_input: bool=False,
213
+
**arguments: Unpack["ConnectorArguments"],
214
+
) -> Tuple[bool, CommandOutput]:
215
+
"""Execute a command with proper shell wrapping."""
216
+
217
+
# Extract and remove control parameters from arguments
218
+
# This modifies arguments dict in place and returns the extracted params
Without proper command wrapping, shell operators and complex commands will fail. For example `timeout 60 bash -c 'command' || true` executed without shell wrapping will result in `bash: ||: command not found`. PyInfra operations and fact gathering rely on shell operators (`&&`, `||`, pipes, redirects) so using `make_unix_command_for_host()` ensures your connector handles these correctly.
244
+
245
+
For complete examples see pyinfra's built-in connectors in `pyinfra/connectors/docker.py`, `pyinfra/connectors/chroot.py`, `pyinfra/connectors/ssh.py` and `pyinfra/connectors/local.py`, as well as the command wrapping utilities in `pyinfra/connectors/util.py`.
246
+
247
+
194
248
## pyproject.toml
195
249
196
250
In order for pyinfra to gain knowledge about your connector, you need to add the following snippet to your connector's `pyproject.toml`:
0 commit comments