Fix container --tty detection in subprocess mode#1306
Conversation
|
I kinda have a feeling this might break pexpect and passwords (not sure we have testing mechanisms set up for that). Someone will have to dig into that aspect and do some validation there. |
|
I've done some manual testing in various scenarios (pexpect w/ passwords, subprocess in container connecting stdin to the input, etc) and it seems to work as expected. However, I'm not 100% certain I've covered all of the scenarios. This really needs some testing from the Controller team to validate that nothing on their side is affected negatively by this. |
|
Is there anything else that needs testing? I'd be happy to continue improving this PR. |
|
|
Hi @Shrews, picking this up again after a long hiatus. I've rebased and reworked the approach based on your earlier feedback. The previous version checked The logic is now in a
This should address the Controller team concern — callers that don't pass |
How to testReproduce the bug from ansible/ansible-navigator#1607 at the runner level: # test_tty_bug.py — run with: python test_tty_bug.py
from ansible_runner.config.command import CommandConfig
import sys, os
for d in ('/tmp/test_runner/artifacts', '/tmp/test_runner/project'):
os.makedirs(d, exist_ok=True)
rc = CommandConfig(
private_data_dir='/tmp/test_runner',
process_isolation=True,
container_image='ghcr.io/ansible/community-ansible-dev-tools:latest',
process_isolation_executable='podman',
input_fd=sys.stdin,
output_fd=sys.stdout,
error_fd=sys.stderr,
)
rc.prepare_run_command('ansible-config', cmdline_args=['init'])
print('runner_mode:', rc.runner_mode)
print('stdin.isatty():', sys.stdin.isatty())
print('Has --tty:', '--tty' in rc.command)On unpatched runner, With this patch, |
|
This is going to need tests. The example you provided looks like an excellent start for an integration test, fwiw. |
|
Added tests and found the fix was incomplete while writing them. The original fix only checked Updated Regarding the earlier concern about breaking pexpect/passwords — this change cannot affect that path. Tests added:
|
|
@Shrews One more note on why My reasoning is that
Checking only That said, I'm not 100% sure I've thought through every scenario — for example, are there any callers (Controller, AWX, or other integrations) that might pass a real-TTY |
Shrews
left a comment
There was a problem hiding this comment.
Your logic, at least initially, seems to make sense to me. I do want to come back to this again and do some manual testing on my own (forgot what I did last time), and also want to run this through some controller testing eventually. Both of those may take a little bit, but will try not to let this linger too long for you.
As far as use cases downstream, unfortunately, I do have much input there. Users do crazy things that we aren't always privilege to... until we break something. 😉
Looks like you have some linting errors to fix up, but thanks for adding the new tests.
270b2b4 to
4848f14
Compare
|
@Shrews Thanks for the review! I've fixed the linting errors in the latest commit, and also local tested the linting. |
ansible-navigator always passes sys.stdin as input_fd regardless of whether the parent process has a real TTY. The previous condition treated any truthy input_fd as a signal to add --tty, causing containers to allocate a pseudo-TTY in non-TTY environments (CI/CD, pipes, cron). This made pagers like `less` hang waiting for input. Extract the decision into _should_allocate_tty() which checks input_fd.isatty() instead of just its presence. pexpect mode is unchanged (always gets --tty). Fixes: ansible/ansible-navigator#1607 Signed-off-by: xz-dev <xiangzhedev@gmail.com>
…tion The initial fix (f0c0a7e) checked only input_fd.isatty(), which covers the CI/CD case where stdin is not a TTY. The original ansible-navigator#1607 scenario is different: stdin IS a TTY but stdout is redirected to a file (e.g. `> ansible.cfg`). input_fd.isatty() still returns True so --tty was still added, polluting output with ANSI escape sequences. _should_allocate_tty() now requires *both* input_fd and output_fd to be real terminals. If either side is redirected the container runs without a pseudo-terminal. pexpect mode is unchanged (always gets --tty). Add unit tests covering all branch combinations of _should_allocate_tty and the CommandConfig containerization, plus integration tests that run `ansible-config init` in a real container with: - file-based stdin (CI/CD scenario) - pty stdin + file stdout (the exact navigator#1607 scenario) Fixes: ansible/ansible-navigator#1607 Signed-off-by: xz-dev <xiangzhedev@gmail.com>
Shorten verbose docstrings in unit and integration tests to single-line summaries (or remove entirely where function names are self-explanatory), and shorten overly long integration test function names. This aligns the new TTY-related tests with the existing test style in the same files. Signed-off-by: xz-dev <xiangzhedev@gmail.com>
…t tests Signed-off-by: xz-dev <xiangzhedev@gmail.com>
Signed-off-by: xz-dev <xiangzhedev@gmail.com>
Signed-off-by: xz-dev <xiangzhedev@gmail.com>
|
Fixed the CI test ab5e76b |
|
https://github.com/ansible/ansible-runner/actions/runs/22068526553/job/63798923163?pr=1306 Seems not due to my code change: |
Yeah, I'll look into it and put up a fix. |
|
|
After it merge to master, will merge to this PR |
…e class Signed-off-by: xz-dev <xiangzhedev@gmail.com>
|
@xz-dev Did you, by any chance, test this change with |
|
Yes, I've verified it with the latest commit. Here is the recording: https://asciinema.org/a/QNLnDkgC83MOcLfj |
Shrews
left a comment
There was a problem hiding this comment.
Thanks for your work on this!
|
Thanks @Shrews for the review and merge! Glad to see this finally land. |



First, stdin not need --tty option, it only dependent --interactive option. Secendly, when running in subprocess mode, disable --tty option if parent process does not have a tty. This prevents the subprocess incorrectly detecting tty and enabling interactive features like
ansible-config init.For example, if you use
ansible-navigator config init -m stdout > config, the subprocess will incorrectly detect tty and waiting 'q' to exit less and cause errors of config. This change avoids that.More code see at here ansible_navigator. ansible_navigator enable input_fd even if in non-tty mode, It is understandable because they are able to control the input and output based on needs.