New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add option to disable streaming to stdout file #937
Conversation
@@ -139,7 +139,8 @@ The **settings** file is a little different than the other files provided in thi | |||
* ``pexpect_timeout``: ``10`` Number of seconds for the internal pexpect command to wait to block on input before continuing | |||
* ``pexpect_use_poll``: ``True`` Use ``poll()`` function for communication with child processes instead of ``select()``. ``select()`` is used when the value is set to ``False``. ``select()`` has a known limitation of using only up to 1024 file descriptors. | |||
|
|||
* ``suppress_ansible_output``: ``False`` Allow output from ansible to not be printed to the screen | |||
* ``suppress_output_file``: ``False`` Allow output from ansible to not be streamed to the ``stdout`` or ``stderr`` files inside of the artifacts directory. | |||
* ``suppress_ansible_output``: ``False`` Allow output from ansible to not be printed to the screen. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a check to make these mutually exclusive? If they are both set ansible would "just run" with no output, maybe we don't care?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AWX will set them both to False
by design. The output is processed by the callback receiver. If someone really wanted the standard out file (which is normally deleted at the end of the run anyway) then we can introduce a setting for them to get it back.
There's a feature in AWX to download the standard out file from a job run. It is illustrative that this works by a completely unrelated method. In the request-response cycle, it is written to disk from the database data and then delivered to the client. Then deleted.
# about being nice | ||
m = mocker.patch('time.sleep') | ||
m.start() | ||
request.addfinalizer(m.stop) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked the timing, and the whole module takes about 3.6 seconds. Maybe this was reducing it to 3.5 or 3.4, but the difference also could have been indistinguishable. I'm using time.sleep
to make the assertion reliable, so that's why I did this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good to me, other than the comment on the tests to re-use the iterate_timeout()
function.
test/unit/test_runner.py
Outdated
stdout_path = Path(rc.artifact_dir) / 'stdout' | ||
# this can be subject to a race condition so we will be patient with the check | ||
start_time = time.time() | ||
while time.time() - start_time < 2.0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use iterate_timeout()
here from test/utils/common.py
. You can find examples in the test code.
test/unit/test_runner.py
Outdated
@@ -154,13 +155,9 @@ def test_stdout_file_write(rc, runner_mode): | |||
assert status == 'successful' | |||
stdout_path = Path(rc.artifact_dir) / 'stdout' | |||
# this can be subject to a race condition so we will be patient with the check | |||
start_time = time.time() | |||
while time.time() - start_time < 2.0: | |||
for _ in iterate_timeout(2.0, 'stdout file to be written', interval=0.2): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can get some pretty slow test VMs, so 2 seconds can be cutting it pretty darn close, which is likely why you see the test failure. I see no reason not to just bump this to, say, 30 seconds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. The first time I checked results I saw 2 configurations failing and after adding the 2 second poll 1 was failing. So this would fit the picture that it's slow, dependent on the hardware.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Interesting... I'm wondering if this was a pre-existing failure of the same type
I can apply the same methods to that assertion. That looks like it may be the proper thing to do. |
The disk space issue aside (no idea why we're seeing that on occasion), each time the new |
FYI, the failure using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing approval until the test failure under pexpect
is figured out.
Would it be a problem for me to do a |
Do a quick poll until assertion is satisfied Use iterate_timeout test util from review comment reuse poll for the stdout file because of race condition Skip test for pexpect because it does not work
aca2bb5
to
dbbe02f
Compare
@Shrews I added the skip, which looks like it's working to stabilize tests. I can make an issue to cover the stdout log file not working with pexpect |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes me a sad panda that we have to skip the test case we explicitly want this feature for, but this change obviously didn't create the error, only exposed it. So I guess skipping it is ok for now.
Fix suppress_output_file bug where event_callback was not called Sorry, I had a major flaw with #937 and I should have tested that better before it was merged. The handle was not passed to pexpect, and that was wrong. The handle is the way that it dispatches events to the event_callback. Even if you do not intend to write to the stdout file, this is necessary. Design-wise, if suppress_output_file is given, we do want to use the stdout handle wrapper, but we do not want to use the stdout handle itself. I think this code structure articulates that about as best as possible. Alternatively, we could create a null handler and pass that to OutputEventFilter, instead of handling the None case. Separately, I may have discovered a bug related to the test failures on the prior PR. ansible-runner/ansible_runner/utils/__init__.py Line 373 in d013044 event_data['stdout'] = stdout_chunk[:-2] if len(stdout_chunk) > 2 else "" This is assuming the .splitlines(True) leaves \r\n at the end of the line. This is... not universal. Because of that, the final character in the echo command gets truncated, because it has a \n without the \r. This looks completely fixable, but I wish to keep that separate. Reviewed-by: David Shrewsbury <None> Reviewed-by: None <None> Reviewed-by: Alexander Sowitzki <dev@eqrx.net>
This addresses #926
My current intention is to make use of the setting (set it to True) in AWX, unconditionally. We don't want the additional disk writes this incurs. If the executor team is okay with the looks of this, I may ask @amolgautam25 to make that PR.
This use case is only concerned with the
pexpect
runner mode. I only messed withsubprocess
here for completeness. The subprocess mode also appears to somehow be connected with the introduction of this behavior. Maybe @ganeshrn has more history to share about this.